{"thread":{"id":"34777","subject":"BUG: git subtree split - revert commit followed by a merge","startedAt":"2013-08-27T13:09:30Z","lastAt":"2013-08-28T07:59:28Z","messageCount":2,"participants":["Machiels, Brecht","Brecht Machiels"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"225990","messageId":"E71F820BDC168F4B91A464A8FD8ABBD8389BD9C7@CH1PRD0310MB391.namprd03.prod.outlook.com","threadId":"34777","inReplyTo":null,"subject":"BUG: git subtree split - revert commit followed by a merge","fromName":"Machiels, Brecht","fromEmail":"brecht.machiels@kla-tencor.com","sentAt":"2013-08-27T13:09:30Z","receivedAt":"2013-08-27T13:09:30Z","isPatch":false,"sender":{"key":"brecht.machiels@kla-tencor.com","avatar":null},"body":"Hello:\n\nI'm running into the problem described in this mailing list post:\n\thttp://thread.gmane.org/gmane.comp.version-control.git/202645\n\n 'git subtree split' fails to reconstruct the history when a revert commit is followed by a merge commit. I have slightly adjusted the test script provided by Fabien in his mailing list post:\n\n    git init\n    \n    # create a directory that is going to be split\n    mkdir doc\n    echo \"TEST\" > doc/README\n    git add doc\n    # commit A\n    git commit -a -m\"first version\"\n    \n    # create a branch with a new commit (Z)\n    git checkout -b test\n    echo \"TEST\" > doc/README1\n    git add doc/README1\n    git commit -a -m\"added README1\"\n    git checkout master\n    \n    # modify the README file (commit B)\n    echo \"TEST_\" > doc/README\n    git commit -a -m\"second version\"\n    \n    # revert the change (commit C)\n    echo \"TEST\" > doc/README\n    git commit -a -m\"revert second version\"\n    # or use git revert HEAD^\n    \n    # split\n    git subtree split --prefix=\"doc\" --branch=TARGET\n    \n    # add another commit (to a file *not* in the subtree dir)\n    echo \"BLA\" > BLA\n    git add BLA\n    git commit -a -m\"third version\"\n    \n    # adding another commit to a file in the subtree dir will \"fix\" things\n    #echo \"MEH\" > doc/MEH\n    #git add doc\n    #git commit -a -m\"fourth version\"\n\n    # the log will show the 3 commits as expected (including B and C)\n    GIT_PAGER= git log --oneline TARGET\n    \n    # merge the test branch\n    git merge -m\"merged test\" test\n    \n    # attempt to re-split; this will fail\n    git subtree split --prefix=\"doc\" --branch=TARGET\n    \n    # see what history split generates\n    git subtree split --prefix=\"doc\" --branch=TARGET2\n\nI have discovered that if the revert commit is followed by another commit that makes changes in the subtree directory, the split will work as expected (see \"fourth version\" above).\n\nSee also this related SO question where I ask for a workaround: http://stackoverflow.com/questions/18465867\n\nBest regards,\nBrecht\n"},{"id":"226081","messageId":"op.w2ioheg99vfd47@bel1pc-0098.adcorp.kla-tencor.com","threadId":"34777","inReplyTo":"E71F820BDC168F4B91A464A8FD8ABBD8389BD9C7@CH1PRD0310MB391.namprd03.prod.outlook.com","subject":"Re: BUG: git subtree split - revert commit followed by a merge","fromName":"Brecht Machiels","fromEmail":"brecht.machiels@kla-tencor.com","sentAt":"2013-08-28T07:59:28Z","receivedAt":"2013-08-28T07:59:28Z","isPatch":false,"sender":{"key":"brecht.machiels@kla-tencor.com","avatar":null},"body":"Hi,\n\nI think I understand what's going on. If there are no net changes in one  \nof the two branches, the id of the merge commit will be the same as that  \nof the last commit on the other branch (pass the -d option to 'git subtree  \nsplit' to see the new commit id's of the split out commits). In that case,  \ngit-subtree will drop the merge commit. I believe this is done because for  \nregular commits, this means that the commit does not make changes to files  \nin the subtree directory. I'm not sure I'm right about this, as I would  \nexpect the merge commit's hash to depend on the hashes of its parent  \ncommits.\n\nI was thinking the solution would be to simply adjust the copy_or_skip  \nfunction to always copy merge commits. However, this may result in the  \nproduced commit history to differ from before (unnecessary merge commits  \nwere previously left out), leading to other problems.\n\nA solution might be to check for the presence of such commit +  \nrevert-commit branches. This can be done by checking for each parent of a  \nmerge commit if it is the ancestor of any of the other parents (using git  \nmerge-base --is-ancestor).\n\nBest regards,\nBrecht\n\nOn Tue, 27 Aug 2013 15:09:30 +0200, Machiels, Brecht  \n<Brecht.Machiels@kla-tencor.com> wrote:\n\n> Hello:\n>\n> I'm running into the problem described in this mailing list post:\n> \thttp://thread.gmane.org/gmane.comp.version-control.git/202645\n>\n>  'git subtree split' fails to reconstruct the history when a revert  \n> commit is followed by a merge commit. I have slightly adjusted the test  \n> script provided by Fabien in his mailing list post:\n>\n>     git init\n>    # create a directory that is going to be split\n>     mkdir doc\n>     echo \"TEST\" > doc/README\n>     git add doc\n>     # commit A\n>     git commit -a -m\"first version\"\n>    # create a branch with a new commit (Z)\n>     git checkout -b test\n>     echo \"TEST\" > doc/README1\n>     git add doc/README1\n>     git commit -a -m\"added README1\"\n>     git checkout master\n>    # modify the README file (commit B)\n>     echo \"TEST_\" > doc/README\n>     git commit -a -m\"second version\"\n>    # revert the change (commit C)\n>     echo \"TEST\" > doc/README\n>     git commit -a -m\"revert second version\"\n>     # or use git revert HEAD^\n>    # split\n>     git subtree split --prefix=\"doc\" --branch=TARGET\n>    # add another commit (to a file *not* in the subtree dir)\n>     echo \"BLA\" > BLA\n>     git add BLA\n>     git commit -a -m\"third version\"\n>    # adding another commit to a file in the subtree dir will \"fix\" things\n>     #echo \"MEH\" > doc/MEH\n>     #git add doc\n>     #git commit -a -m\"fourth version\"\n>\n>     # the log will show the 3 commits as expected (including B and C)\n>     GIT_PAGER= git log --oneline TARGET\n>    # merge the test branch\n>     git merge -m\"merged test\" test\n>    # attempt to re-split; this will fail\n>     git subtree split --prefix=\"doc\" --branch=TARGET\n>    # see what history split generates\n>     git subtree split --prefix=\"doc\" --branch=TARGET2\n>\n> I have discovered that if the revert commit is followed by another  \n> commit that makes changes in the subtree directory, the split will work  \n> as expected (see \"fourth version\" above).\n>\n> See also this related SO question where I ask for a workaround:  \n> http://stackoverflow.com/questions/18465867\n"}]}