My usecase is:
I have a two branches of a repo containing submodules.
I want to set up auto-integrate of these two branches. But whenever there are submodule updates on both branches, my auto integrate script fails with conflicts on submodules. Is there way to ask git to ignore the changes in submodule pointers during the merge?
Or provide something like merge=ours for the given submodules?
I've read this here.
I tried the merge strategies in the above page for submodule folder like this (but it only works for files)
submodule-name merge=ours
To be honest, I was surprised too, but the documentation quickly explains what is happening:
I guess the answer to the question "why don't merging strategies work?" is: because there is no merging process between different submodules versions. The approach suggested by the doc is still not that complex if you need to do an actual merge, but it is even "easier" in your case.
Suppose you are on
masterand you want to mergemy_branchin it. There are 3 scenarios:git merge my_branchThis is very well explained by the documentation I already linked, so there is no reason why I should repeat it. I still suggest you to read it because you could end up in an unexpected situation. I am telling you about it at the end of the answer.
git merge -Xours my_branchI would not know if this is a correct way to solve this, but there is a very simple shortcut to clear any conflict on submodules. Because git does not do any merge operation on submodule versions, it only tells you about the diverging versions. So, if you look at the index, you still find the 3 versions coming from the 3-way merge
(output of
git ls-files -s)The first one (e826e1b) is the merge base, but you are interested on the one with index 2. Unfortunately, I think you cannot refer to the submodule revision with the common
:2:./submodwhileadding it to the index because it is not a real path. The easy shortcut I told you about is this one :)git add submodAnd then you can
commit. It automatically keeps themastersubmodule version, but it is not the best way of course, since the behaviour could change in some future versions of git. I will show you the other way for the next scenario.git merge -Xtheirs my_branchHere things get complicated: we cannot use the above trick (simple
addthat for now defaults to themastersubmodule revision), because now we need the revision with index 3, which is:3:./submodthat does not work with theaddcommand.You can also update the index with the plumbing command
update-indexand pass a raw cache-info entry, like:mode
160000is the one used for submodules (more specifically for git links),cd5caa86...is the object we want to add to the index, andsubmodis the path. Here, strangely, putting the submodule name works. If you need to script this, you cannot obviously put a hard-code object there, but you can retrieve it withIn the end, this is the command to run to keep
theirsversion of submodule:Instead, to keep
oursversion, replace:3:with:2:.Git does not merge submodules, but could reuse a merge
Also this part is very well explained in the reference, but you need to be very careful. In summary, git does not try to merge your submodules, unless:
oursortheirs).In my humble opinion, git team should add an option to give us more control on how we want to handle these situations. By the way, you can always allow the commit and then
--amendit, or fix it before committing usinggit merge --no-commit. In both cases you cannot use the index revisions (like:2:./submod), butHEAD^1andHEAD^2in the first case, and theMERGE_HEADin the second case. If this is a very unlikely scenario, just skip it, otherwise I would commit and--amendif it is acceptable.Conclusions
I hope there is an easier way to merge branches with different submodule revisions, so do not consider this answer as the one and only possibility. Moreover, after the merge you may need to
deinitand reinitialize (or resync) your submodule, but as far as this is scriptable, this is not a real issue. If I were you, I would create an alias containing all these operations.