Re: Handling merge conflicts a bit more gracefully..

2 messages, 2 authors, 2016-06-15 · open the first message on its own page

Re: Handling merge conflicts a bit more gracefully..

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:41:59

quoted
quoted
quoted
quoted
"LT" == Linus Torvalds [off-list ref] writes:
LT> Yeah, ok, so the fact that we allow missing things in the
LT> index (which was debatable to start with) makes for
LT> exceptions.

Not just that.  Another big difference is that we allow _extra_
things in the index in two-tree case (i.e. local additions).
But I do not think these exceptions are necessarily bad.

And you are right that two-tree is _very_ different from
three-way merge.

LT> We could certainly be stricter about the index contents, and
LT> require that they match the branch we're merging from
LT> exactly, rather than be a subset.

I guess great minds do not always think alike.  I was going in
quite the opposite direction.  I vaguely recall saying this
before on this list ;-)

With the current three-way code, if I rewrite two-way merge
using the three-way "read-tree -m H I-mixed-with-H M" (emulated
two-tree fast forward, where "I" denotes "tree that would have
resulted from the original cache"), it would give quite
different results from the "carry forward" two-way code we have.
So in that sense, three-way and two-way are quite different.

I have, however, not convinced myself that this difference is
coming from some fundamental difference between two-tree fast
forward and three-way merge.  If desirable results fall out
naturally for the "emulated two-way" case by handling three-way
case more carefully (e.g. not having stricter index requirements
than necessary), that would be wonderful.  I think, for example,
there are places where we have too strict index requirements in
three-way merge (grep for '(ALT)' in t/t1000*.sh test file).

I probably am dreaming, though.

LT> I think the case that is more important (and more likely to
LT> hit people) is when they have something in their working
LT> tree that conflicts with the merge, and then what you want
LT> is really that the current "update" code do the three-way
LT> merge in the working directory, not that it's done on the
LT> index file contents.

LT> ..., but I don't think the index file is the most important
LT> case. The more important case is the one that the three-way
LT> merge doesn't handle either!

I agree with all of the above.  Their working tree has changes
from H, and merging M into H conflicts with those changes.  That
means, although they did not actually make a formal commit, what
they have is essentially this:

         cache contents
         is here
         v
      ---I---
     /       ^work tree contents is here
  --H
     \
      ----------M

which means we are exactly in the same situation as "merge I and
M pivoting on H" three-way merge, with a dirty work tree.  Any
solution and help we would give to the end-user for the
three-way case would automatically help this two-way case,
wouldn't it?

I do not think index file is important either; maybe I am not
really understanding your argument.  I fully accept the new
world order with today's merge-one-file-script changes, that the
merge result will be left in the work tree for the user to
verify and sort out.  What I am trying to do in the above
picture is to help the end-user forward-porting differences in I
since H (along with the work tree changes since I) when doing a
fast-forward from H to M happens, using the files in the work
tree.

Re: Handling merge conflicts a bit more gracefully..

From: Linus Torvalds <torvalds@osdl.org>
Date: 2016-06-15 22:41:59


On Wed, 8 Jun 2005, Junio C Hamano wrote:
quoted
quoted
quoted
quoted
quoted
"LT" == Linus Torvalds [off-list ref] writes:
LT> Yeah, ok, so the fact that we allow missing things in the
LT> index (which was debatable to start with) makes for
LT> exceptions.

Not just that.  Another big difference is that we allow _extra_
things in the index in two-tree case (i.e. local additions).
But I do not think these exceptions are necessarily bad.
Well, they'd be bad in a three-way merge.

The reason they aren't bad in a two-way merge is that you don't commit the 
result - the commits have been done already. 

That's really the big conceptual difference between two-way and three-way:  
never mind the merge algorithm itself.

(In fact, in many ways, two-way merges are really just the same as a 
one-way merge, except it now knows where it came from, so it can do sanity 
checking).

As to working tree changes:
which means we are exactly in the same situation as "merge I and
M pivoting on H" three-way merge, with a dirty work tree.  Any
solution and help we would give to the end-user for the
three-way case would automatically help this two-way case,
wouldn't it?
Yes.

In fact, there's a fairly simple solution, which is to remove the current 
check for "verify_uptodate()" and instead replace it with the "update" 
phase not just writing the file, but actually doing a three-way merge on 
it.

NOTE! This would not affect the resulting _tree_ in any way at all. It 
would literally only affect how we write out the working directory. Right 
now we just fail when the working file isn't up-to-date, and that could be 
replaced with instead doing a

	merge W I M

where "W" is the working file, "I" is the index file, and "M" is the merge 
result that we currently just write out directly.

In the special case of I == M, we already do _exactly_ this: we know that
since I=M, the merge will be W, so we don't do the update at all.

So in fact, doing a 3-way merge is really a generalization of what we
already do, and removes a failure case.

NOTE! This 3way merge is fundamentally _different_ from the 3-way merge
that is done by "git-merge-one-file-script" that we already do. _That_
3-way merge is done not on the working files, but on the results in the
trees, while this new 3way merge would be done purely in the working
directory (ie it wouldn't make sense without the "-u" flag).

If we do this, I'd personally suggest it be another flag, possibly "-u3" 
instead of just plain "-u".

		Linus
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help