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