I find that working with git submodules, I often encounter problems merging between commits which do contain a given submodules and those which represent the same code as a normal directory. Small reproducing example:
# Create one project, to be used as a subproject later on
git init a
cd a
echo aaa > aa
git add -A
git commit -m a1
cd ..
# Create a second project, containing a as a normal directory initially
git init b
cd b
mkdir a b
echo aaa > a/aa
echo bbb > b/bb
git add -A
git commit -m b1
# Replace directory with submodule
git rm -r a
git submodule add ../a a
git commit -m b2
# Try to create branch from the pre-submodule state of affairs
git checkout -b branch HEAD^
This already gives an error:
error: The following untracked working tree files would be overwritten by checkout:
a/aa
Please move or remove them before you can switch branches.
Aborting
In order to avoid the error, I deinitialize all submodules first:
# Create feature brach starting at version without submodule
git submodule deinit .
git checkout -b branch HEAD^
echo abc > b/bb
git commit -a -m b3
As you can see, the feature branch is completely unrelated to the submodule, modifying a different set of files. Which makes this whole problem particularly annoying.
# Try to merge the feature branch
git checkout master
git merge branch
This fails again, with an error message I don't fully understand:
CONFLICT (file/directory): There is a directory with name a in branch. Adding a as a~HEAD
Automatic merge failed; fix conflicts and then commit the result.
I get the same error if I do a git submodule update --init
before the git merge branch
. I don't see any a~HEAD
anywhere, neither in my directory tree nor in the output from git status
, which reads like this:
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
Changes to be committed:
modified: b/bb
Unmerged paths:
(use "git add <file>..." to mark resolution)
added by us: a
If I do git add a
as suggested, I get another error:
error: unable to index file a
fatal: updating files failed
If I do git submodules update --init
just before the merge, then I can do git add a
successfully. But if I forget to do so, and then try doing that after the merge, I receive this error message:
Submodule 'a' (…/a) registered for path 'a'
Skipping unmerged submodule a
How do I recover from this situation? Something other than git merge --abort
, since I'd like to use it for things like git rebase
as well, and since in some scenarios (don't know how to reproduce) I couldn't even abort the merge cleanly, and had to do a hard reset instead.
How can I avoid it in the first place? Is there some magic setting which makes git do the right thing with submodules vs. directories during merges, so that I don't have to manually post-process a merge which only modifies files unrelated to the submodules?