{"thread":{"id":"22731","subject":"unexpected git-merge result","startedAt":"2010-02-19T21:35:54Z","lastAt":"2010-02-22T17:24:33Z","messageCount":5,"participants":["Dale Rowley","Junio C Hamano","Dmitry Potapov"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"135112","messageId":"loom.20100219T202452-35@post.gmane.org","threadId":"22731","inReplyTo":null,"subject":"unexpected git-merge result","fromName":"Dale Rowley","fromEmail":"ddrowley3@juno.com","sentAt":"2010-02-19T21:35:54Z","receivedAt":"2010-02-19T21:35:54Z","isPatch":false,"sender":{"key":"ddrowley3@juno.com","avatar":null},"body":"Our branch history looked something like the following:\n\n  B---C\n /     \\\nA---D---E---H\n     \\     /\n      F---G\n\nIn commit D a few lines were added to a file, and then in commit G the same\nlines were removed. When branches E and G were merged, those lines unexpectedly\nre-appeared in the merge commit (H), even though no other commits had touched\nthat file.\n\nI think I understand why this happened: git-merge-base reports that the common\nancestor for E and G is A. Since those lines don't appear in that file in\ncommits A or G, git-merge assumes that they were added independently on branch\nE, so it decides to keep the lines in the merged result.\n\nThis merge problem arises because although A is the most recent common ancestor\nof branches E and G in general, it is *not* the most recent common ancestor as\nfar as that single file is concerned. The most recent common ancestor for that\nparticular file is commit D.\n\nThis is worrisome because I imagine the converse will also be a potential\nproblem: lines are removed in commit D, and then re-added in commit G, and they\nwill unexpectedly disappear in the merge (H). So my question is whether this is\na bug in git (ie, shouldn't git be considering independent common ancestors for\neach file that is merged)? This doesn't seem like a particularly unique or rare\nscenario - how is everyone else preventing these kinds of problems? \n\nDale\n"},{"id":"135119","messageId":"7vaav4amjj.fsf@alter.siamese.dyndns.org","threadId":"22731","inReplyTo":"loom.20100219T202452-35@post.gmane.org","subject":"Re: unexpected git-merge result","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-02-19T22:27:44Z","receivedAt":"2010-02-19T22:27:44Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dale Rowley <ddrowley3@juno.com> writes:\n\n> Our branch history looked something like the following:\n>\n>   B---C\n>  /     \\\n> A---D---E---H\n>      \\     /\n>       F---G\n>\n> In commit D a few lines were added to a file, and then in commit G the same\n> lines were removed. When branches E and G were merged, those lines unexpectedly\n> re-appeared in the merge commit (H), even though no other commits had touched\n> that file.\n>\n> I think I understand why this happened: git-merge-base reports that the\n> common ancestor for E and G is A.\n\nDo you?  I don't.\n\nD is the merge base between E and G.  A and D are both common ancestor\nbetween E and G, but because D is a descendant of A, A is not a merge\nbase (the definition of merge-base is \"common ancestors none of whose\nchildren is common ancestor\").  A is not.\n\nAre you sure you really have ancestry relationship between D and G?  If\nthe history were like this:\n\n   B---C\n  /     \\\n A---D---E---H\n  \\         /\n   F-------G\n\nand both D and F add the same set of \"few lines\", and G removes it, then I\ncan understand how you would get these \"removed by G\" lines appear in H,\nas the side branch F--G didn't have no net effect on these lines and D is\nthe only one that added them.\n\nIt can happen if F is a cherry-pick of D and G is a revert of F, for\nexample.\n"},{"id":"135141","messageId":"loom.20100220T031401-572@post.gmane.org","threadId":"22731","inReplyTo":"7vaav4amjj.fsf@alter.siamese.dyndns.org","subject":"Re: unexpected git-merge result","fromName":"Dale Rowley","fromEmail":"ddrowley3@juno.com","sentAt":"2010-02-20T03:45:09Z","receivedAt":"2010-02-20T03:45:09Z","isPatch":false,"sender":{"key":"ddrowley3@juno.com","avatar":null},"body":"Junio C Hamano <gitster <at> pobox.com> writes:\n\n> It can happen if F is a cherry-pick of D and G is a revert of F, for\n> example.\n> \n\nYou're exactly right. I overlooked the cherry-pick, which clears things up a\nbit. But the basic problem remains:\n\nA----D---E---H\n \\          /\n  B--D'----G\n\nG only removed a few of the lines that were brought over in the cherry-pick\n(D'), so it was surprising when they re-appeared in H. Intuitively, one would at\nleast expect a conflict in H since D'+G is asserting that these lines should not\nexist, whereas D (on the other branch) is asserting that they should. I can see\nhow it would be difficult to make git-merge account for this though, so maybe\nthis is just a subtle gotcha when merging branches? Is there an easy way to\navoid this gotcha?\n\nDale\n"},{"id":"135242","messageId":"20100222054425.GC10191@dpotapov.dyndns.org","threadId":"22731","inReplyTo":"loom.20100220T031401-572@post.gmane.org","subject":"Re: unexpected git-merge result","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2010-02-22T05:44:25Z","receivedAt":"2010-02-22T05:44:25Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Sat, Feb 20, 2010 at 03:45:09AM +0000, Dale Rowley wrote:\n> \n> You're exactly right. I overlooked the cherry-pick, which clears things up a\n> bit. But the basic problem remains:\n> \n> A----D---E---H\n>  \\          /\n>   B--D'----G\n> \n> G only removed a few of the lines that were brought over in the cherry-pick\n> (D'), so it was surprising when they re-appeared in H. Intuitively, one would at\n> least expect a conflict in H since D'+G is asserting that these lines should not\n> exist, whereas D (on the other branch) is asserting that they should. I can see\n> how it would be difficult to make git-merge account for this though, so maybe\n> this is just a subtle gotcha when merging branches? Is there an easy way to\n> avoid this gotcha?\n\ngit merge does 3-way merge, which means that it does not look at whole\nhistory but only on the current state and the merge base. So, if you\nlook at changes between A and G then those lines were not touched, and\nA-E adds those lines, thus the end result is that these lines are added.\n\n\nDmitry\n"},{"id":"135325","messageId":"loom.20100222T173851-763@post.gmane.org","threadId":"22731","inReplyTo":"20100222054425.GC10191@dpotapov.dyndns.org","subject":"Re: unexpected git-merge result","fromName":"Dale Rowley","fromEmail":"ddrowley3@juno.com","sentAt":"2010-02-22T17:24:33Z","receivedAt":"2010-02-22T17:24:33Z","isPatch":false,"sender":{"key":"ddrowley3@juno.com","avatar":null},"body":"Dmitry Potapov <dpotapov <at> gmail.com> writes:\n\n> > \n> > G only removed a few of the lines that were brought over in the cherry-pick\n> > (D'), so it was surprising when they re-appeared in H. \n> \n> git merge does 3-way merge, which means that it does not look at whole\n> history but only on the current state and the merge base.\n\nYes, but my point is that this is the wrong thing to do in the case that I\ndescribed above. If you explicitly remove some content in your branch, then it's\nbad when a merge causes it to re-appear without even any conflicts. The opposite\nis also possible (you add content to your branch and it silently disappears\nduring a merge), so shouldn't this be a big concern?\n"}]}