Re: [RFC/PATCH 05/18] Add testcase for --index-only merges needing the recursive strategy

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Junio C Hamano <gitster@xxxxxxxxx> writes:

> Elijah Newren <newren@xxxxxxxxx> writes:
>
>> +test_expect_failure '--index-only with rename/modify works in non-bare-clone' '
>> +	git checkout B^0 &&
>> +
>> +	git merge --index-only -s recursive C^0 &&
>> +
>> +	echo "Making sure the working copy was not updated" &&
>> +	test ! -f b &&
>> +	test -f a &&
>> +	test $(git rev-parse B:a) = $(git hash-object a) &&
>> +
>> +	echo "Making sure the index was updated" &&
>> +	test 1 -eq $(git ls-files -s | wc -l) &&
>> +	test $(git rev-parse B:a) = $(git rev-parse :b)
>
> The most crucial test that is missing (hence prevents reviewers from
> judging if --index-only is a good idea at all) is the test on HEAD.
> Does it record a merge between B and C and move HEAD there, i.e.
>
> 	test $(git rev-parse HEAD^1) = $(git rev-parse B) &&
> 	test $(git rev-parse HEAD^2) = $(git rev-parse C)
>
> or does it make a merge but does not advance HEAD, i.e.
>
> 	test $(git rev-parse HEAD) = $(git rev-parse B)
>
> I fear that it may give a great headache to end users if you move
> HEAD in a repository with a working tree to point at the merge
> result--how do they reconcile the difference between the working
> tree (which was based on B) and the index and HEAD (which is now
> based on the result of the merge)?  The next "git commit -a" would
> appear that it would revert the changes brought in by this merge,
> wouldn't it?

And if the expectation that is not spelled out by this new test is
that the merge does not advance HEAD, the command does not make much
sense either, because there is no way for you to find out the merge
result.

Let's step back a bit.  This may or may not be what you are aiming
at, but I think I can buy a series whose title is "merge without
working tree" if the big-picture objective of the topic were to
support this workflow:

    0. I am working on my own branch that is not 'master'.

    1. I see somebody else worked on and finished a good topic
       'en/topic'.  My work is not yet in a good shape, and I do not
       want to switch to 'master' only to merge 'en/topic' to
       'master', but 'en/topic' is so good and my urge to merge it
       to 'master' is strong.

    2. Hence I want a way to merge 'en/topic' to 'master' and
       advance the tip of 'master', without using my working tree
       (or the index or my HEAD for that matter), without disrupting
       my current state.

    3. For simplicity, I can live with it if the early version of
       that "merge en/topic to master" operation is incapable of
       handling conflicts.  Then I'd say "huh, I'd need to manually
       inspect the merge result so I'll do that later" and continue
       what I was doing, or I'd say "OK, let's really have a look",
       save what I was doing in a temporary commit and switch to
       'master' to do the usual "git merge en/topic".

    4. But it would be even better if I could give a temporary
       directory to it as a scratch-pad area, and if I was asked to
       help it resolving conflicts by editing conflicted files in
       the scratch-pad area.

In any case, what is in my current index (or HEAD) is no use for
merging en/topic into master, so the command should not care or
touch not just what is in my working tree (which gives the operation
the same requirement as your series, i.e. "do not touch or require a
working tree") but also what is in my index or where my HEAD is.

The low-level ingredients that support "git merge", namely, "git
read-tree -m COMMON OURS THEIRS", actually has a support to make
this kind of "merge without fully populated working tree" possible,
by considering the lack of working tree file an equivalent to having
an unmodified working tree file (I suspect that merge-recursive is
probably broken with this regard, as it was mostly done without
knowing that we anticipated such a need in early life of Git long
before merge-recursive was invented).  We can give an empty
"scratch-pad area" as a temporary working tree, create a temporary
index out of 'master' (in the above example), perform the usual
three-way merge with
    
    GIT_DIR=... point at the real thing ...
    GIT_INDEX_FILE=... point at a temporary file ...
    export GIT_DIR GIT_INDEX_FILE
    rm -fr /var/tmp/scratchpad && mkdir /var/tmp/scratchpad
    cd /var/tmp/scratchpad
    base=$(git merge-base master en/topic)
    git read-tree -m $base master en/topic

and run "git merge -s resolve" to drive "git merge-one-file".  This
would populate /var/tmp/scratchpad with files that are involved in
the merge, without wasting diskspace for files in 'master' that does
not change, and you can edit them, "git add" these paths, and then
do a "git write-tree" to create the tree that represents the merge
result.  You obviously need to avoid touching HEAD when recording
that tree as a merge commit and advance the tip of 'master' (as HEAD
is still on my own unrelated branch), but that part is trivial
(i.e. we have written "git commit" at least twice).

Of course, if you are not going to support merges that need manual
conflict resolution, you do not need the scratchpad and the end user
experience would be simpler (i.e. you do not have to think about how
they resolve, record the resolution, etc.)  And your "merge only in
index" topic would fit well in that picture.

But then, using the current index and the HEAD as the place to merge
into is still wrong.  I think this is better done as a separate
command, not "git merge" but perhaps something like

    $ git merge-to en/topic master

or something.  "git merge --into=master en/topic" is also a
possibility.

But as I said in the early part of this message, this may or may not
be what you are aiming at.  The above is the most sensible tangent
that I can think of that may be related to "merge only in index".
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]