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?
Submodules are very static and only track specific commits. Submodules do not track git refs or branches and are not automatically updated when the host repository is updated. When adding a submodule to a repository a new . gitmodules file will be created.
No you should not add a, the merge is not supposed to change it. What you should run is
git reset a
So you ignore the "chage" for a.
PS: apparently git merely checks existense of a directory, so if you
git submodule deinit a
rmdir a
before merging, it will succeed. Not sure if this is what you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With