Hello all,
In many situations, if you have a submodule conflict during a rebase, and you type 'git diff' to get a summary of the situation, you will get an empty diff. Here's a simple transcript for one such case (I'm sorry I can't make it much shorter), tested on git version 2.0.3.693.g996b0fd:
git init
mkdir b
cd b
git init
git commit --allow-empty -m "submodule initial"
cd ..
git submodule add ./b
git commit -am "parent initial"
git branch dev
cd b
touch a
git add a
git commit -m "submodule master"
cd ..
git commit -am "parent master"
git checkout dev
git submodule update
cd b
touch b
git add b
git commit -m "submodule dev"
cd ..
git commit -am "parent dev"
git rebase master
git diff bThe last output is:
diff --cc b
index 4b1b6c6,c423df2..0000000
--- a/b
+++ b/bAs it turns out, this behavior is logical in a perverse sort of way.
- The rebase operation doesn't go about updating your submodule
checkouts, so whatever is in the file is what the submodule
was pointing to before your initiated the rebase. - By default, 'git diff' on a merge conflict (implicitly
'git diff --cc') only will report if the submodule's HEAD
differs from all of the merge heads. So if you only had
one commit which changed the submodule, you're probably
on that commit, and so the "current state" of the submoduleHowever, just because behavior is logical, doesn't mean it is user friendly. There are a few problems here:
1. Git is treating the lagging submodule HEAD as if it were
actually a resolution that you might want for the conflict.
Actually, it's basically almost always wrong (in the example
above, if you commit it you'll be discarding commits made on
master.) There is a sorter of wider UI issue here where Git
can't tell if you've legitimately changed the HEAD pointer
of a submodule, or if you checked out a new revision with different
submodule pointers and forgot to run 'git submodule update'.
(But by the way, you can't even do that here, because this is
a merge!) 2. The behavior of not reporting the diff when the diff for one
branch is non-empty is illogical: for submodules (whose "file
contents" are so short), you basically always want some hashes,
and not an empty diff. Doubly so when the "resolution" is
bogus (c.f. (1)).Of course, changing behavior in a backwards-incompatible way is never a good way, so it's not exactly obvious what should be done here. I would recommend tweaking the default combined diff behavior for submodules and adding an admonition to the user that the submodules have not been updated in the rebase message (I can submit a patch for this if people agree if it's a good idea), but maybe that's too much of a behavior change.
By the way, the difference between 'git diff -c' and 'git diff --cc' does not seem to be documented anywhere, except for an oblique comment in diff-format.txt "Note that 'combined diff' lists only files which were modified from all parents." -- the user expected, of course, to figure out that 'combined diff' here refers to --cc, but not -c.
Cheers, Edward