This Git warning occurs when merging branches that have divergent submodule histories. Git cannot automatically resolve which commit the submodule should point to because both branches have made independent changes to the submodule reference.
When you see "Failed to merge submodule (commits don't follow merge-base)", Git is telling you that the two branches you're trying to merge contain different submodule commit references that don't share a common ancestor in the expected merge path. In Git, a submodule is a pointer to a specific commit in another repository. When you merge two branches, Git normally finds the "merge-base" (the common ancestor commit) and applies changes from both branches. However, if both branches have updated the submodule to point to different commits that don't follow a linear path from this merge-base, Git cannot automatically determine which commit should win. This is fundamentally different from a regular file conflict because Git cannot simply show you conflicting lines of text - instead, it needs you to decide which submodule commit (or a merge of both) should be used in the resulting merge commit.
First, determine which commits each branch is pointing to in the submodule:
git diffThis shows output like:
diff --cc lib
index abc1234,def5678..0000000
--- a/lib
+++ b/libThe two SHA-1 hashes (abc1234 and def5678) are the submodule commits from each branch.
Navigate into the submodule and check if the commits can be merged:
cd lib
git log --oneline abc1234..def5678
git log --oneline def5678..abc1234This helps you understand whether one commit is an ancestor of the other, or if they truly diverged.
If you want to keep the submodule version from the branch you're merging INTO (current branch):
git checkout --ours -- lib
git add libOr to keep the version from the branch you're merging FROM:
git checkout --theirs -- lib
git add libReplace "lib" with your actual submodule path.
If both branches contain important changes, merge them inside the submodule:
cd lib
git fetch origin
git checkout def5678 # The commit from the other branch
git merge abc1234 # Merge in the commit from current branch
# Resolve any conflicts within the submodule
git commit -m "Merge submodule changes"
cd ..
git add libThis creates a new merge commit in the submodule that includes changes from both branches.
Git sometimes suggests using update-index to accept a specific resolution:
git update-index --cacheinfo 160000 <desired-commit-hash> libThe "160000" mode indicates a submodule (gitlink). Replace <desired-commit-hash> with the commit you want the submodule to point to.
After resolving the submodule conflict:
git status # Verify submodule shows as resolved
git commit # Complete the merge commitIf you were doing a stash pop, remember to drop the stash manually since git stash pop doesn't auto-drop when conflicts occur:
git stash dropIf this error came from git stash pop:
git reset HEAD lib # Unstage the conflicted submodule
git checkout -- lib # Reset to the current branch's version
git submodule update lib # Update submodule to match
git stash drop # Clean up the stashNote: Don't include a trailing slash after the submodule name - shell tab-completion often adds one, which will cause the command to fail.
### Understanding merge-base with submodules
The "merge-base" is the commit that Git identifies as the common ancestor when merging. For regular files, Git computes a three-way merge using this base. Submodules complicate this because the submodule commit reference is just a SHA-1 hash - Git cannot meaningfully merge two different hashes.
### Recursive submodule merging
Git 2.14+ supports git merge --recurse-submodules which attempts to automatically merge submodule changes:
git merge --recurse-submodules=on-demand feature-branchThis will try to fast-forward submodules when possible, or create merge commits within them when both sides have changes.
### Preventing future conflicts
To minimize submodule merge conflicts:
1. Keep submodule updates in dedicated commits
2. Coordinate submodule version bumps across branches
3. Consider using git config submodule.recurse true to auto-update submodules
4. Use merge rather than rebase for branches with submodule changes when possible
### When rebasing fails
Rebasing with submodules is particularly problematic because rebase replays commits one by one. Each replayed commit that touches a submodule may conflict. In these cases, git merge is often cleaner than git rebase, even though the history looks messier.
### Submodule configuration options
Relevant git config options for submodule merging:
- submodule.recurse: Automatically recurse into submodules for many commands
- diff.submodule: Controls how submodule diffs are displayed (log, short, diff)
- status.submodulesummary: Show submodule commit summaries in git status
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git