We have a repo with a bunch of submodules and we are currently working on a develop branch.
Starting from the same common commit, two developers, A and B, made some changes to some files (unimportant here I think) and added a new revision of one of the submodules, then commited to develop. Now develop holds rev1 of subm commited by developer A, while B's develop branch holds rev2 of subm, thus creating a conflict when B tries to pull changes made by A from remote.
This is what git status gives to B, after a merge with conflicts:
Your branch and 'origin/develop' have diverged,
and have 1 and 1 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: path/to/another/submodule
modified: path/to/file/file.html
Now, whenever B tries to commit, it gets:
U path/to/subm
error: Committing is not possible because you have unmerged files.
hint: Fix them up in the work tree, and then use 'git add/rm <file>'
hint: as appropriate to mark resolution and make a commit.
fatal: Exiting because of an unresolved conflict.
I tried looking up for solutions and they all seem to suggest to add the conflicted files to the stage to mark them as resolved, but git status does not list any unmerged files.
It looks like I am missing something here, any help would be gladly appreciated.
What you need to realize here is that a Git submodule is another Git repository.
Let's label all the repositories in play here. I'm going to assume that both developers have their own clones, so that there is another Git at some third location (perhaps GitHub, perhaps a corporate server, whatever it might be):
path/to/another/submodule.path/to/subm.When developer A does some work in DevASuper, he:
X;git addto add the new commit inDevASubmod2as an updated gitlink entry; andThe new commit, in DevASuper, contains a gitlink that says "use commit
Xin submodule #2".Developer A can push this new commit to the central superproject (perhaps on a branch). Before he does so, he should also push the new DevASubmod2 commit to CentralSubmod2 (also perhaps on a branch). Whoever merges these, to the branch named
developon CentralSuper, should make sure the submodule repository commit in CentralSubmod2 is available to everyone first, presumably by merging that first. (The person who merges them could be developer A himself. This is just a general pattern: the submodule commit must be available first.)Let's call the final commit, on the
developbranch in CentralSuper, commitSX, with theSstanding for Super and theXstanding for commitX(commit SX uses / refers-to commit X from submodule#2).Now we get to Developer B
At any time before or at this point, developer B can make new commits in any of his three repositories. Based on what you've posted, it seems likely that he has made a new commit in DevBSubmod2. Let's call this commit
Y. Like commitX, it is some big ugly hash ID.Like developer A, developer B should—and apparently did—now make a new commit in his DevBSuper repository using
git addandgit commit. We'll call this commitSY.So now, developer B wants to merge his new commit with the final result from whoever did the merge of developer A's commit. But commit
SXsays use hash X whileSYsays use hash Y.This is the submodule conflict you are seeing:
The superproject that B is working with/on has a commit,
SY, that says use Y, and a commit,SX, that says use X. These "use" things are gitlinks in these two commits.Git cannot resolve this on its own. If the correct resolution is use
X, developer B should put that in his superproject's index. If the correct resolution is useY, developer B should put that in his superproject's index. Chances are very good, however, that neither commitXnor commitYis the correct commit to use for a new commit in developer B's superproject repository.If this last is true, what developer B must now do is:
XandY.Z. Make sure this is the current commit in DevBSubmod2.path/to/submas commitZ, usinggit add path/to/subm. This resolves the merge conflict and says that the correct gitlink goes to commitZ. Neither commitXnor commitYis correct;Zis correct.SZ.At this point developer B can now send these back to the various central repositories, again keeping in mind that the new submodule commit must be available to everyone before making commit
SZavailable to everyone, since usingSZrequires that they obtain commitZ.