13

We are using submodules and we are new to git.

We often see merge conflicts for the submodules themselves, no files are conflicted, just the submodule. There are multiple versions listed in the output of git submodule summary. We resolve them by running git add <submodule> in the superproject.
But today we had a developer lose a commit of the submodule when she resolved the conflict in this manner.
Does running a git add choose the remote version? Shouldn't the contents of the submodule get merged? If she made changes in the submodule and committed them (which I see), then why would that commit disappear after she ran the pull and resolved the conflict?

Cœur
  • 37,241
  • 25
  • 195
  • 267
user561638
  • 1,299
  • 3
  • 15
  • 26

3 Answers3

12

Your local submodule and the remote submodule have diverged.

git checkout --theirs submodulename

or for your version:

git checkout --ours submodulename

and then commit the changes with git add and commit the changes.

Note: Your shell may add a trailing slash to the submodulename if you tabcomplete, since it is also a subdirectory. If so, you need to delete it or you'll get:

error: pathspec 'submodulename/' did not match any file(s) known to git.
Andrew Wagner
  • 22,677
  • 21
  • 86
  • 100
  • 3
    This isn't working for me: upstream changes the module, and while merging in their changes I tried 'git checkout --theirs ios_src' but in 'git diff origin/dev_ios .' I still see my local oid marked '-dirty' and the new one not marked dirty. I was expecting to see the my local line to be the new oid with a '-dirty' mark. Committing also leaves me with my oid. Going into the modules and explicitly checking the root out, then adding it works, but that's tedious. – android.weasel Jun 27 '16 at 11:13
11

Both file conflicts and submodule conflicts occur when your current branch and the branch-you-want-to-merge-into have diverged.

It merely means an ambiguous situation exists -- you could legitimately want either to "win" in any given case. So, while it may seem "annoying", they merely highlight your rich options to specify what you want (and you must specify what you want). (And, all that programmers do every day is merely to specify detail.)

It seems like the git-add-the-submodule-on-the-superproject should have worked. However, you also had the option to git-checkout-on-the-superproject right away. This is mentioned in this link (resolving submodule conflicts), which talks about the difference between file conflicts and summodule conflicts, and how to resolve them:

http://pacific.mpi-cbg.de/wiki/index.php/Git_Conflicts

charley
  • 5,913
  • 1
  • 33
  • 58
  • 7
    I think the link is not currently working. WebArchive to the rescue: http://web.archive.org/web/20100925080451/http://pacific.mpi-cbg.de/wiki/index.php/Git_Conflicts – Ricardo Sanchez-Saez Nov 28 '12 at 11:35
  • git checkout --theirs or for your version: git checkout --ours – Andrew Wagner May 19 '14 at 11:21
  • 1
    Clarification to your initial statement: The potential conflicted files/submodules must have both changed in both diverged paths. Simply a branch diverging does not mean you will get conflicts. – void.pointer Apr 28 '15 at 14:53
0

At least Git 2.38 (Q3 2022) provides more detailed help messages while merging submodules, especially in case of merge conflict.

See commit 565577e, commit 34ce504, commit a5834b7 (18 Aug 2022) by Elijah Newren (newren).
See commit 4057523 (04 Aug 2022) by Calvin Wan (CalvinWan0101).
(Merged by Junio C Hamano -- gitster -- in commit df3c129, 25 Aug 2022)

submodule merge: update conflict error message

Signed-off-by: Calvin Wan

When attempting to merge in a superproject with conflicting submodule pointers that cannot be fast-forwarded or trivially resolved, the merge fails and Git prints an error message that accurately describes the failure, but does not provide steps for the user to resolve the error.

Git is left in a conflicted state, which requires the user to:

  1. merge submodules or update submodules to an already existing commit that reflects the merge
  2. add submodules changes to the superproject
  3. finish merging superproject

These steps are non-obvious for newer submodule users to figure out based on the error message and neither git submodule status(man) nor git status(man) provide any useful pointers.

Update error message to provide steps to resolve submodule merge conflict.

Although the message is long, it also has the id of the submodule commit that needs to be merged, which could be useful information for the user.

Additionally, 5 merge failures that resulted in an early return have been updated to reflect the status of the merge.

  1. Null merge base (null o): CONFLICT_SUBMODULE_NULL_MERGE_BASE added as a new conflict type and will print updated error message.
  2. Null merge side a (null a): BUG(). See discussion
  3. Null merge side b (null b): BUG(). See for discussion
  4. Submodule not checked out: added NEEDSWORK bit
  5. Submodule commits not present: added NEEDSWORK bit The errors with a NEEDSWORK bit deserve a more detailed explanation of how to resolve them.
    See here for more context.

You now have a line of advice to resolve a merge conflict in a submodule.

The first argument is the submodulename, and the second argument is the abbreviated id of the commit that needs to be merged.
For example:

go to submodule (mysubmodule), and either merge commit abc1234
or update to an existing commit which has merged those changes

Also, new message:

Recursive merging with submodules currently only supports trivial cases.

Please manually handle the merging of each conflicted submodule.
This can be accomplished with the following steps:

sub1:
- come back to superproject and run:"
  git add sub1
to record the above merge or update"
- resolve any other conflicts in the superproject
- commit the resulting index in the superproject
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250