new read-tree questions.
From: Junio C Hamano <hidden>
Date: 2016-06-15 22:41:59
I am trying to understand the new git-read-tree, by using
git-resolve-script as an example and also reading read-tree.c; I
am somewhat confused.
* two-way merge (git-read-tree -m $H $M)
My understanding is that the current index is allowed to be
empty, but if it is not, they are kept at stage0, and each of
them must match $H and must be up-to-date if the merge involves
them.
To summarize my understanding of what should happen for each
path:
stage0 (index) stage1 ($H) stage2 ($M)
------------------------------------------------------------
no such path no such path no such path
* this does not happen (the code would not see such thing).
----------------------------------------------------------
no such path no such path exists
* take $M without complaining.
----------------------------------------------------------
no such path exists (does not matter) *0*
* although index does not match $H, we do not reject, so
that a merge can happen on an empty cache. We take $M.
----------------------------------------------------------
exists no such path no such path
* reject, because index does not match $H.
----------------------------------------------------------
exists no such path exists (index!=$M)
* reject, because index does not match $H.
----------------------------------------------------------
exists no such path exists (index=$M) *1*
* take $M (same as "keep stage0").
----------------------------------------------------------
exists exists (index!=$H) (does not matter)
* reject, because index does not match $H.
----------------------------------------------------------
exists exists (index=$H) no such path *2*
* path is removed.
----------------------------------------------------------
exists exists (index=$H) exists
* take stage2.
----------------------------------------------------------
Does the above matrix represent the intended behaviour?
I think I understand why we would want *0*, but this asymmetry
feels wrong.
I am having trouble with the case *1*. This would call
twoway_check with !seen_stage1 and it says OK, because the
merged tree has the same contents as what we started with. Is
it to help the case where" the merged tree changes things the
same way we already have as our local change" case?
Also I am not sure if the code does the right thing for case
*2*. If I am reading the code right, for such a path, we will
see stage0 and stage1, and at that point say seen_stage1 = 1 and
keep stage0 entry in "old". Then we continue on to the next
path. When it happens to be:
- stage0: we barf because we still have our "old".
- stage1: we barf because our "old" does not match the new
path; !path_matches(old,ce) triggers.
- stage2: we barf because our "old" does not match the new
path; twoway_check(old, seen_stage1, ce) triggers.
Only when such a "exists-exists-removed" were the last entry,
the control falls out of the loop and "unmatched with a new
entry?" check takes care of it without barfing. The path is
removed which is what I understand you want to happen in the
case *2*.
Maybe my version of intended behaviour for case *2* is wrong,
but then I do not understand why.
I'll do a similar matrix for three-way merge case later and
probably ask more questions.