{"thread":{"id":"27816","subject":"rerere affects handling of git-stash-pop merge conflicts","startedAt":"2011-07-14T17:09:51Z","lastAt":"2011-07-25T22:31:32Z","messageCount":6,"participants":["Phil Hord","Martin von Zweigbergk","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"171340","messageId":"4E1F22DF.7060209@cisco.com","threadId":"27816","inReplyTo":null,"subject":"rerere affects handling of git-stash-pop merge conflicts","fromName":"Phil Hord","fromEmail":"hordp@cisco.com","sentAt":"2011-07-14T17:09:51Z","receivedAt":"2011-07-14T17:09:51Z","isPatch":false,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"I was investigating a git-stash-pop anomaly when I ran across this one.\nI think this is residual breakage from [1] bb0a484 (mergetool: Skip\nautoresolved paths, 2010-08-17).  A similar problem aimed at 'git merge'\nwas ostensibly fixed by [2] 2f59c9 (mergetool: don't skip modify/remove\nconflicts, 2011-02-16).\n\n[1] http://thread.gmane.org/gmane.comp.version-control.git/153420\n[2] http://thread.gmane.org/gmane.comp.version-control.git/164622\n\n\nSummary:\nAfter a 'git stash pop' with conflicts, 'git mergetool' fails to notice\nthe conflicted files if 'rerere.enabled=true'.  git mergetool\nerroneously reports 'no files need merging'.\n\nAfter a 'git merge' with conflicts, 'git mergetool' seems to work ok in\neither case.\n\nHere's my test script:\n\n------8<------ /tmp/stash.sh\n#!/bin/bash\n\n#enable/disable rerere for this test\ngit config --global rerere.enabled ${1:false}\n\n# run the test\nrm -rf foo\nmkdir foo && cd foo && git init &&\necho A>file && git add file && git commit --quiet -m \"A\" &&\necho B>file && git stash &&\necho C>file && git add file && git commit --quiet -m \"C\" &&\ngit stash pop\n\ngit mergetool\n------8<------ /tmp/stash.sh\n\ngit --version\n    git version 1.7.6.178.g55272\n\n# With rerere.enabled=false, it works ok (mergetool offers to\n# merge the conflicting file):\n./stash.sh false\n\n    Initialized empty Git repository in /tmp/foo/.git/\n    Saved working directory and index state WIP on master: ac67a86 A\n    HEAD is now at ac67a86 A\n    Auto-merging file\n    CONFLICT (content): Merge conflict in file\n    merge tool candidates: meld opendiff kdiff3 tkdiff xxdiff\n    tortoisemerge gvimdiff diffuse ecmerge p4merge araxis bc3 vimdiff\n    emerge\n    Merging:\n    file\n\n    Normal merge conflict for 'file':\n      {local}: modified\n      {remote}: modified\n    Hit return to start merge resolution tool (xxdiff): ^C\n\n# But with rerere.enabled=true, mergetool thinks there is no conflict:\n./stash.sh true\n\n    Initialized empty Git repository in /tmp/foo/.git/\n    Saved working directory and index state WIP on master: d40e77b A\n    HEAD is now at d40e77b A\n    Auto-merging file\n    CONFLICT (content): Merge conflict in file\n    merge tool candidates: meld opendiff kdiff3 tkdiff xxdiff\n    tortoisemerge gvimdiff diffuse ecmerge p4merge araxis bc3 vimdiff\n    emerge\n    No files need merging\n\nPhil\n"},{"id":"171430","messageId":"4E20A0D9.4030404@cisco.com","threadId":"27816","inReplyTo":"4E1F22DF.7060209@cisco.com","subject":"Re: rerere affects handling of git-stash-pop merge conflicts","fromName":"Phil Hord","fromEmail":"hordp@cisco.com","sentAt":"2011-07-15T20:19:37Z","receivedAt":"2011-07-15T20:19:37Z","isPatch":false,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"git rerere is misleading us after a conflicted 'git stash pop'.  There \n_is_ an unresolved merge conflict, but .git/MERGE_RR exists and is \nempty, even though there is no previously recorded resolution.\nThis causes git mergetool to skip over our conflicted file since he now \nuses 'git rerere remaining' to find the unresolved conflicts.\n\nI think one of these is true, but I'm not sure which one.\n\n   A. rerere _should not_ be triggered at all by \"stash pop\" conflicts\nor\n   B. rerere _should_ be correctly and completely triggered by \"stash \npop\" conflicts\nor\n   C. 'git mergetool' should not be expected to work after a failed \"git \nstash pop\"\n\nI'm hoping the right answer is B, but I would also accept A.\n\nfwiw - 'git stash pop' calls 'merge-recursive' at the end, and this is \nwhere the problem appears.  I have not decoded git-merge-recursive's use \nthere enough to figure out where it's gone wrong.\n\nPhil\n\n\nOn 07/14/2011 01:09 PM, Phil Hord wrote:\n> I was investigating a git-stash-pop anomaly when I ran across this one.\n> I think this is residual breakage from [1] bb0a484 (mergetool: Skip\n> autoresolved paths, 2010-08-17).  A similar problem aimed at 'git merge'\n> was ostensibly fixed by [2] 2f59c9 (mergetool: don't skip modify/remove\n> conflicts, 2011-02-16).\n>\n> [1] http://thread.gmane.org/gmane.comp.version-control.git/153420\n> [2] http://thread.gmane.org/gmane.comp.version-control.git/164622\n>\n>\n> Summary:\n> After a 'git stash pop' with conflicts, 'git mergetool' fails to notice\n> the conflicted files if 'rerere.enabled=true'.  git mergetool\n> erroneously reports 'no files need merging'.\n>\n> After a 'git merge' with conflicts, 'git mergetool' seems to work ok in\n> either case.\n>\n> Here's my test script:\n>\n> ------8<------ /tmp/stash.sh\n> #!/bin/bash\n>\n> #enable/disable rerere for this test\n> git config --global rerere.enabled ${1:false}\n>\n> # run the test\n> rm -rf foo\n> mkdir foo&&  cd foo&&  git init&&\n> echo A>file&&  git add file&&  git commit --quiet -m \"A\"&&\n> echo B>file&&  git stash&&\n> echo C>file&&  git add file&&  git commit --quiet -m \"C\"&&\n> git stash pop\n>\n> git mergetool\n> ------8<------ /tmp/stash.sh\n>\n> git --version\n>      git version 1.7.6.178.g55272\n>\n> # With rerere.enabled=false, it works ok (mergetool offers to\n> # merge the conflicting file):\n> ./stash.sh false\n>\n>      Initialized empty Git repository in /tmp/foo/.git/\n>      Saved working directory and index state WIP on master: ac67a86 A\n>      HEAD is now at ac67a86 A\n>      Auto-merging file\n>      CONFLICT (content): Merge conflict in file\n>      merge tool candidates: meld opendiff kdiff3 tkdiff xxdiff\n>      tortoisemerge gvimdiff diffuse ecmerge p4merge araxis bc3 vimdiff\n>      emerge\n>      Merging:\n>      file\n>\n>      Normal merge conflict for 'file':\n>        {local}: modified\n>        {remote}: modified\n>      Hit return to start merge resolution tool (xxdiff): ^C\n>\n> # But with rerere.enabled=true, mergetool thinks there is no conflict:\n> ./stash.sh true\n>\n>      Initialized empty Git repository in /tmp/foo/.git/\n>      Saved working directory and index state WIP on master: d40e77b A\n>      HEAD is now at d40e77b A\n>      Auto-merging file\n>      CONFLICT (content): Merge conflict in file\n>      merge tool candidates: meld opendiff kdiff3 tkdiff xxdiff\n>      tortoisemerge gvimdiff diffuse ecmerge p4merge araxis bc3 vimdiff\n>      emerge\n>      No files need merging\n>\n> Phil\n>\n>\n>\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n"},{"id":"171437","messageId":"4E20AB81.3050005@cisco.com","threadId":"27816","inReplyTo":"4E20A0D9.4030404@cisco.com","subject":"[PATCH/RFC] Add two basic tests for \"rerere remaining\"","fromName":"Phil Hord","fromEmail":"hordp@cisco.com","sentAt":"2011-07-15T21:05:05Z","receivedAt":"2011-07-15T21:05:05Z","isPatch":true,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"After a 'git stash apply' which results in a conflicted file,\ngit mergetool can be used to work on the conflicts.  However,\nwhen rerere.enabled=true, git mergetool determines the list\nof unresolved file conflicts by asking 'git rerere remaining'.\n\nThere is a problem with this because rerere does not record\nthe 'git stash apply' conflicts and so 'git rerere remaining'\ndoes not report them.\n\nDemonstrate this failing so it can be studied and addressed.\n\nAlso add a very basic test for 'git rerere remaining' after\na normal merge conflict.\n\nSigned-off-by: Phil Hord <hordp@cisco.com>\n---\n\nThis patch adds one failing test and one working test.\n\nThe working test is very limited and just repeats the\nsame test as the 'rerere status' one for 'rerere remaining'.\nA better test should probably be added, one that demonstrates\nand confirms the differences between 'rerere status' and\n'rerere remaining'.  I don't understand this difference\nwell enough to code that test, though.\n \n t/t4200-rerere.sh |   38 ++++++++++++++++++++++++++++++++++++++\n 1 files changed, 38 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh\nindex 36255d6..a96ebad 100755\n--- a/t/t4200-rerere.sh\n+++ b/t/t4200-rerere.sh\n@@ -96,10 +96,42 @@ test_expect_success 'rerere.enabled works, too' '\n \tgrep ^=======$ $rr/preimage\n '\n \n+test_expect_success 'set up conflicted stash apply' '\n+\trm -rf .git/rr-cache &&\n+\tgit config rerere.enabled true &&\n+\n+\tgit reset --hard &&\n+\tgit checkout master &&\n+\tgit show second:a1 >a1 &&\n+\n+\t# should be 1 modified file and no unmerged files\n+\ttest $(git ls-files -m |wc -l) = 1 &&\n+\ttest $(git ls-files -u |wc -l) = 0 &&\n+\n+\tgit stash save &&\n+\tgit checkout first &&\n+\n+\ttest_must_fail git stash apply &&\n+\n+\t# there should be three states for one unresolved file\n+\tcnt=$(git ls-files -u | wc -l) &&\n+\techo $cnt &&\n+\ttest $cnt = 3\n+'\n+\n+test_expect_failure 'rerere-remaining correctly reports stash-apply conflicts' '\n+\techo a1 >expect &&\n+\tgit rerere status >out &&\n+\ttest_cmp expect out &&\n+\tgit rerere remaining >out &&\n+\ttest_cmp expect out\n+'\n+\n test_expect_success 'set up rr-cache' '\n \trm -rf .git/rr-cache &&\n \tgit config rerere.enabled true &&\n \tgit reset --hard &&\n+\tgit checkout second &&\n \ttest_must_fail git merge first &&\n \tsha1=$(perl -pe \"s/\t.*//\" .git/MERGE_RR) &&\n \trr=.git/rr-cache/$sha1\n@@ -160,6 +192,12 @@ test_expect_success 'rerere status' '\n \ttest_cmp expect out\n '\n \n+test_expect_success 'rerere remaining' '\n+\techo a1 >expect &&\n+\tgit rerere remaining >out &&\n+\ttest_cmp expect out\n+'\n+\n test_expect_success 'first postimage wins' '\n \tgit show first:a1 | sed \"s/To die: t/To die! T/\" >expect &&\n \n-- \n1.7.6.8.gd2879\n"},{"id":"171454","messageId":"alpine.DEB.2.00.1107152208530.12060@debian","threadId":"27816","inReplyTo":"4E1F22DF.7060209@cisco.com","subject":"Re: rerere affects handling of git-stash-pop merge conflicts","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2011-07-16T02:19:27Z","receivedAt":"2011-07-16T02:19:27Z","isPatch":false,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"On Thu, 14 Jul 2011, Phil Hord wrote:\n\n> Summary:\n> After a 'git stash pop' with conflicts, 'git mergetool' fails to notice\n> the conflicted files if 'rerere.enabled=true'.  git mergetool\n> erroneously reports 'no files need merging'.\n\nIt seems to be because git-stash uses git merge-recursive directly\ninstead of calling git merge. I don't know why git merge-recursive is\nused directly. It has been like that ever since git-stash was\nintroduced in f2c66ed (Add git-stash script, 2007-06-30).\n"},{"id":"171522","messageId":"7voc0szhzn.fsf@alter.siamese.dyndns.org","threadId":"27816","inReplyTo":"alpine.DEB.2.00.1107152208530.12060@debian","subject":"Re: rerere affects handling of git-stash-pop merge conflicts","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-07-17T21:59:08Z","receivedAt":"2011-07-17T21:59:08Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Martin von Zweigbergk <martin.von.zweigbergk@gmail.com> writes:\n\n> On Thu, 14 Jul 2011, Phil Hord wrote:\n>\n>> Summary:\n>> After a 'git stash pop' with conflicts, 'git mergetool' fails to notice\n>> the conflicted files if 'rerere.enabled=true'.  git mergetool\n>> erroneously reports 'no files need merging'.\n>\n> It seems to be because git-stash uses git merge-recursive directly\n> instead of calling git merge. I don't know why git merge-recursive is\n> used directly. It has been like that ever since git-stash was\n> introduced in f2c66ed (Add git-stash script, 2007-06-30).\n\nBut \"stash pop/apply\" should never call \"merge\" directly, as it is not\ninterested in creating (nor preparing to create, with \"merge --no-commit\")\na new merge commit, nor doing the history level three-way merge.\n\nCalling merge-recursive backend is used as a way to run a three-way tree\nmerge with explicitly specified three trees.\n"},{"id":"172023","messageId":"4E2DEEC4.4050000@cisco.com","threadId":"27816","inReplyTo":"7voc0szhzn.fsf@alter.siamese.dyndns.org","subject":"[PATCH] Add two basic tests for \"rerere remaining\"","fromName":"Phil Hord","fromEmail":"hordp@cisco.com","sentAt":"2011-07-25T22:31:32Z","receivedAt":"2011-07-25T22:31:32Z","isPatch":true,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"After a 'git stash apply' which results in a conflicted file,\ngit mergetool can be used to work on the conflicts.  However,\nwhen rerere.enabled=true, git mergetool determines the list\nof unresolved file conflicts by asking 'git rerere remaining'.\n\nThere is a problem with this because rerere does not record\nthe 'git stash apply' conflicts and so 'git rerere remaining'\ndoes not report them.\n\nDemonstrate this failing so it can be studied and addressed.\n\nAlso add a very basic test for 'git rerere remaining' after\na normal merge conflict.\n\nSigned-off-by: Phil Hord <hordp@cisco.com>\n---\n\nThis patch adds one failing test and one working test.\n\nThe working test is very limited and just repeats the\nsame test as the 'rerere status' one for 'rerere remaining'.\nA better test should probably be added, one that demonstrates\nand confirms the differences between 'rerere status' and\n'rerere remaining'.  I don't understand this difference\nwell enough to code that test, though.\n\nThis patch is the same as before, but dropping the /RFC. \n\n t/t4200-rerere.sh |   38 ++++++++++++++++++++++++++++++++++++++\n 1 files changed, 38 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh\nindex 36255d6..a96ebad 100755\n--- a/t/t4200-rerere.sh\n+++ b/t/t4200-rerere.sh\n@@ -96,10 +96,42 @@ test_expect_success 'rerere.enabled works, too' '\n \tgrep ^=======$ $rr/preimage\n '\n \n+test_expect_success 'set up conflicted stash apply' '\n+\trm -rf .git/rr-cache &&\n+\tgit config rerere.enabled true &&\n+\n+\tgit reset --hard &&\n+\tgit checkout master &&\n+\tgit show second:a1 >a1 &&\n+\n+\t# should be 1 modified file and no unmerged files\n+\ttest $(git ls-files -m |wc -l) = 1 &&\n+\ttest $(git ls-files -u |wc -l) = 0 &&\n+\n+\tgit stash save &&\n+\tgit checkout first &&\n+\n+\ttest_must_fail git stash apply &&\n+\n+\t# there should be three states for one unresolved file\n+\tcnt=$(git ls-files -u | wc -l) &&\n+\techo $cnt &&\n+\ttest $cnt = 3\n+'\n+\n+test_expect_failure 'rerere-remaining correctly reports stash-apply conflicts' '\n+\techo a1 >expect &&\n+\tgit rerere status >out &&\n+\ttest_cmp expect out &&\n+\tgit rerere remaining >out &&\n+\ttest_cmp expect out\n+'\n+\n test_expect_success 'set up rr-cache' '\n \trm -rf .git/rr-cache &&\n \tgit config rerere.enabled true &&\n \tgit reset --hard &&\n+\tgit checkout second &&\n \ttest_must_fail git merge first &&\n \tsha1=$(perl -pe \"s/\t.*//\" .git/MERGE_RR) &&\n \trr=.git/rr-cache/$sha1\n@@ -160,6 +192,12 @@ test_expect_success 'rerere status' '\n \ttest_cmp expect out\n '\n \n+test_expect_success 'rerere remaining' '\n+\techo a1 >expect &&\n+\tgit rerere remaining >out &&\n+\ttest_cmp expect out\n+'\n+\n test_expect_success 'first postimage wins' '\n \tgit show first:a1 | sed \"s/To die: t/To die! T/\" >expect &&\n \n-- 1.7.6.8.gd2879\n"}]}