Thread (3 messages) flat view 3 messages, 3 authors, 2016-06-15

Re: [PATCH (1b)] merge-recursive.c: Add more generic merge_recursive_generic()

From: Daniel Barkalow <hidden>
Date: 2016-06-15 22:45:09

On Wed, 13 Aug 2008, Junio C Hamano wrote:
Daniel Barkalow [off-list ref] writes:
quoted
quoted
Puhh, I've not dug into merging stuff that deep, but for me it does not
look that this can be done in a useful way, i.e. merge_working_tree()
does not do a recursive merge.
Ah, true. It's actually doing a single merge in the way that 
merge_recursive would do a single merge. I think it ought to be doing 
a recursive merge, but that's probably a change for later, anyway. (This 
is for -m, which essentially picks the uncommited changes versus the old 
branch, applied to the new branch uncommitted)
Why would you think it should be doing a recursive merge?  It shouldn't.

Think of builtin-merge-recursive.c::merge_trees() as a fancier version of
3-tree variant of "unpack_trees()", with -m and -u option.

When you want to perform an exact three-way merge (i.e. you have two
states O and B, and you want to apply changes between O and B to your
state A, and you _precisely_ know what O is) that's the interface you
would want to use, not the recursive one.  The recursive behaviour is
desirable only when you have A and B and need to infer where O should be,
and/or there are multiple O's to deal with (i.e. running "git-merge B"
when you are at A).
I understand that you know exactly what the change is, but I'm not 
convinced that you don't want to consider how O is related to A in 
determining who to apply that change to A. My naive impression was:

 - the difference between O and B is to change X to Y, and we can 
   determine this exactly
 - we need to find X' in A to change it to Y'
 - we can more accurately find X' in A if we find Z in the common 
   ancestors of O and A such that X in O corresponds to Z in the
   ancestors, and we get similar benefits in determining the right Y'

That is, we care about the common ancestor not only for finding the 
relevant change in the near side to apply, but also for finding how to 
apply it to the far side.
In all the potential users of merge-recursive machinery, namely, "revert",
"cherry-pick", "stash apply", "am -3", and "checkout -m", you know what
single common tree to use for your three-way merge.  These operations,
when done with direct C call into merge machinery, should NOT be using the
"recursive" one.
I agree that they should all be using the same mechanism, but I'm not sure 
it shouldn't be recursive or take history into account.

And I'd certainly believe that just running our merge-recursive won't 
actually do anything clever with the rest of the history, and that 
merge_trees() is the most suitable method currently available (which is 
essentially why I ended up using it in checkout -m, not entirely 
realizing that I'd removed the "recursive" aspect in the process of 
skipping parts of merge_recursive that weren't relevant).

Maybe merge_trees should get the two sides as structs with a struct tree * 
and a char * branch name, and the struct could someday get optional struct 
commit *s for the lineage of the side if somebody comes up with a method 
for merging that makes use of the component changes.

	-Daniel
*This .sig left intentionally blank*
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help