git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* unexpected git-merge result
@ 2010-02-19 21:35 Dale Rowley
  2010-02-19 22:27 ` Junio C Hamano
  0 siblings, 1 reply; 5+ messages in thread
From: Dale Rowley @ 2010-02-19 21:35 UTC (permalink / raw)
  To: git

Our branch history looked something like the following:

  B---C
 /     \
A---D---E---H
     \     /
      F---G

In commit D a few lines were added to a file, and then in commit G the same
lines were removed. When branches E and G were merged, those lines unexpectedly
re-appeared in the merge commit (H), even though no other commits had touched
that file.

I think I understand why this happened: git-merge-base reports that the common
ancestor for E and G is A. Since those lines don't appear in that file in
commits A or G, git-merge assumes that they were added independently on branch
E, so it decides to keep the lines in the merged result.

This merge problem arises because although A is the most recent common ancestor
of branches E and G in general, it is *not* the most recent common ancestor as
far as that single file is concerned. The most recent common ancestor for that
particular file is commit D.

This is worrisome because I imagine the converse will also be a potential
problem: lines are removed in commit D, and then re-added in commit G, and they
will unexpectedly disappear in the merge (H). So my question is whether this is
a bug in git (ie, shouldn't git be considering independent common ancestors for
each file that is merged)? This doesn't seem like a particularly unique or rare
scenario - how is everyone else preventing these kinds of problems? 

Dale

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: unexpected git-merge result
  2010-02-19 21:35 unexpected git-merge result Dale Rowley
@ 2010-02-19 22:27 ` Junio C Hamano
  2010-02-20  3:45   ` Dale Rowley
  0 siblings, 1 reply; 5+ messages in thread
From: Junio C Hamano @ 2010-02-19 22:27 UTC (permalink / raw)
  To: Dale Rowley; +Cc: git

Dale Rowley <ddrowley3@juno.com> writes:

> Our branch history looked something like the following:
>
>   B---C
>  /     \
> A---D---E---H
>      \     /
>       F---G
>
> In commit D a few lines were added to a file, and then in commit G the same
> lines were removed. When branches E and G were merged, those lines unexpectedly
> re-appeared in the merge commit (H), even though no other commits had touched
> that file.
>
> I think I understand why this happened: git-merge-base reports that the
> common ancestor for E and G is A.

Do you?  I don't.

D is the merge base between E and G.  A and D are both common ancestor
between E and G, but because D is a descendant of A, A is not a merge
base (the definition of merge-base is "common ancestors none of whose
children is common ancestor").  A is not.

Are you sure you really have ancestry relationship between D and G?  If
the history were like this:

   B---C
  /     \
 A---D---E---H
  \         /
   F-------G

and both D and F add the same set of "few lines", and G removes it, then I
can understand how you would get these "removed by G" lines appear in H,
as the side branch F--G didn't have no net effect on these lines and D is
the only one that added them.

It can happen if F is a cherry-pick of D and G is a revert of F, for
example.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: unexpected git-merge result
  2010-02-19 22:27 ` Junio C Hamano
@ 2010-02-20  3:45   ` Dale Rowley
  2010-02-22  5:44     ` Dmitry Potapov
  0 siblings, 1 reply; 5+ messages in thread
From: Dale Rowley @ 2010-02-20  3:45 UTC (permalink / raw)
  To: git

Junio C Hamano <gitster <at> pobox.com> writes:

> It can happen if F is a cherry-pick of D and G is a revert of F, for
> example.
> 

You're exactly right. I overlooked the cherry-pick, which clears things up a
bit. But the basic problem remains:

A----D---E---H
 \          /
  B--D'----G

G only removed a few of the lines that were brought over in the cherry-pick
(D'), so it was surprising when they re-appeared in H. Intuitively, one would at
least expect a conflict in H since D'+G is asserting that these lines should not
exist, whereas D (on the other branch) is asserting that they should. I can see
how it would be difficult to make git-merge account for this though, so maybe
this is just a subtle gotcha when merging branches? Is there an easy way to
avoid this gotcha?

Dale

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: unexpected git-merge result
  2010-02-20  3:45   ` Dale Rowley
@ 2010-02-22  5:44     ` Dmitry Potapov
  2010-02-22 17:24       ` Dale Rowley
  0 siblings, 1 reply; 5+ messages in thread
From: Dmitry Potapov @ 2010-02-22  5:44 UTC (permalink / raw)
  To: Dale Rowley; +Cc: git

On Sat, Feb 20, 2010 at 03:45:09AM +0000, Dale Rowley wrote:
> 
> You're exactly right. I overlooked the cherry-pick, which clears things up a
> bit. But the basic problem remains:
> 
> A----D---E---H
>  \          /
>   B--D'----G
> 
> G only removed a few of the lines that were brought over in the cherry-pick
> (D'), so it was surprising when they re-appeared in H. Intuitively, one would at
> least expect a conflict in H since D'+G is asserting that these lines should not
> exist, whereas D (on the other branch) is asserting that they should. I can see
> how it would be difficult to make git-merge account for this though, so maybe
> this is just a subtle gotcha when merging branches? Is there an easy way to
> avoid this gotcha?

git merge does 3-way merge, which means that it does not look at whole
history but only on the current state and the merge base. So, if you
look at changes between A and G then those lines were not touched, and
A-E adds those lines, thus the end result is that these lines are added.


Dmitry

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: unexpected git-merge result
  2010-02-22  5:44     ` Dmitry Potapov
@ 2010-02-22 17:24       ` Dale Rowley
  0 siblings, 0 replies; 5+ messages in thread
From: Dale Rowley @ 2010-02-22 17:24 UTC (permalink / raw)
  To: git

Dmitry Potapov <dpotapov <at> gmail.com> writes:

> > 
> > G only removed a few of the lines that were brought over in the cherry-pick
> > (D'), so it was surprising when they re-appeared in H. 
> 
> git merge does 3-way merge, which means that it does not look at whole
> history but only on the current state and the merge base.

Yes, but my point is that this is the wrong thing to do in the case that I
described above. If you explicitly remove some content in your branch, then it's
bad when a merge causes it to re-appear without even any conflicts. The opposite
is also possible (you add content to your branch and it silently disappears
during a merge), so shouldn't this be a big concern?

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-02-22 17:24 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-19 21:35 unexpected git-merge result Dale Rowley
2010-02-19 22:27 ` Junio C Hamano
2010-02-20  3:45   ` Dale Rowley
2010-02-22  5:44     ` Dmitry Potapov
2010-02-22 17:24       ` Dale Rowley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).