Can't resolve merge conflict with git submodule folder
Asked Answered
L

5

21

I have two git branches, develop and redesign that I need to merge. I have a submodule called library where its updates are being tracked by develop. When I run 'git merge' it says library has been modified by both even though I haven't touched the library submodule. When I click on library in VS Code to see the conflicting changes I see this:

diff --cc library
index 749618f9,589a7ae5..00000000
--- a/library
+++ b/library

I've tried deleting the library folder and running 'git submodule update' while in the redesign branch before merging with no success. I added ignore = all to the .gitmodules file in redesign but didn't work. How do I get rid of the merge conflict with this submodule?

Leath answered 23/8, 2019 at 20:23 Comment(0)
L
15

I solved the issue. I found the answer from this reply to similar StackOverflow question: https://mcmap.net/q/149728/-what-does-it-mean-when-git-says-a-file-quot-needs-update-quot. When I ran 'git add' to library and committed it, the issue went away. Another developer on my team changed the hash associated with the library submodule.

Leath answered 30/8, 2019 at 20:9 Comment(2)
Thank you. The accepted answer is a non-answer tbh.Leilani
Part of my answer is the StackOverflow question I referenced.Leath
Y
18

The problem is that library has been modified in both branches, with respect to the merge-base commit. The trick here is understanding what it means for a submodule to be "modified".

Remember that the essence of any submodule is that your superproject is referring to some other Git repository. That other Git repository—the one being used as a submodule—has no idea that it is being used as a submodule. It's just a regular old Git repository.1 It has commits. The true name of any one commit is its hash ID. The superproject that uses this submodule runs Git commands in the submodule to tell it to git checkout some particular commit by hash ID, which result in the submodule Git being in detached HEAD mode.

Meanwhile, back in the superproject: This repository is an ordinary Git repository. It has commits. The true name of each commit is some hash ID, though generally you'll git checkout some branch name. The branch name will resolve to some particular hash ID, and your superproject Git will check out that commit via that branch name—e.g., develop—and now be on some particular commit, e.g., a123456.... So let's say you're on commit a123456.

Somewhere in commit a123456, there is a file-like object that is not actually a file, but instead is a gitlink. This gitlink object in the commit contains the raw hash ID of some commit that exists in the submodule. In your case, this gitlink is the entry for the name library and it holds, e.g., 589a7ae5. That's the submodule's commit: your superproject Git will, if you run git submodule update, enter the submodule Git and command it to git checkout 589a7ae5.

So: each commit in the superproject has a "file" named library that is really a gitlink, and that stores some hash ID. You've now run:

git checkout develop
git merge redesign

(or maybe vice versa). The git merge command has located the commits designated by the branch names develop and redesign, along with a third commit that is the merge base of these other two commits.

All three of these commits have (or lack: one of yours is 00000000) a gitlink entry named library. The three hash IDs in these gitlinks are all different. Git is now attempting to merge two diffs:

  • One diff says starting with gitlink X in the merge base, replace that gitlink with hash ID Y.
  • The other diff says starting with X in the merge base, replace that with Z.

These two directives—replace with Y, and replace with Z—conflict with each other. Git does not know which one is correct (if in fact either one is correct).

Your job, in order to resolve this particular merge conflict, is to pick the correct hash ID for the submodule. Once you know the correct hash ID—how you find this is up to you2—you simply temporarily change into the submodule Git repository and run git checkout hash, then return to the superproject and run git add library. Your superproject Git now records the new hash ID in the gitlink that will go into the merge commit, and the merge conflict is resolved.

When you have resolved all merge conflicts—including ordinary file ones, if any—and are ready to commit the merge, run git merge --continue or git commit to finish the merge. The merge commit will have, as its gitlink for library, the hash ID you added.

(If the correct thing is to stop using the submodule entirely, you can git rm library instead of first checking out the correct submodule hash, then git adding the name.)


1This skips some technical details by which it's possible to discover that this submodule repository lives within some superproject. The important thing is that most of Git is blissfully unaware of these details: the submodule thinks it's independent, as it were. Moreover, a typical submodule Git repo is a clone of some other Git repo, and that other Git repo is totally unaware of the clone, so even if the clone—the submodule you're using—were aware that it was a submodule, its origin would still not be aware.

2A typical example method for finding the correct hash ID begins with:

cd library

followed by various git log and/or git show and/or git checkout commands, or maybe gitk --all or whatever you like to use to view a Git repository. Eventually, you spot some hash ID that looks good and run git checkout on it, so as to update the work-tree in this repository, then cd back out of the submodule and build and test the project. This process naturally leaves the submodule on the correct commit, so that you don't have to re-git checkout the right hash ID.

Yardmaster answered 23/8, 2019 at 21:21 Comment(1)
@Sasino: would it help if I used boldface for the sentence beginning with "your job"?Yardmaster
L
15

I solved the issue. I found the answer from this reply to similar StackOverflow question: https://mcmap.net/q/149728/-what-does-it-mean-when-git-says-a-file-quot-needs-update-quot. When I ran 'git add' to library and committed it, the issue went away. Another developer on my team changed the hash associated with the library submodule.

Leath answered 30/8, 2019 at 20:9 Comment(2)
Thank you. The accepted answer is a non-answer tbh.Leilani
Part of my answer is the StackOverflow question I referenced.Leath
M
11

Using vscode with submodules: where the UI handles most things well.

However, with a submodule merge conflict, I could not find a way to fix it.

All that was needed was to run this in the cli:

git add submodule-name
Magnifico answered 5/8, 2020 at 17:42 Comment(0)
E
0

In my case, my branch and the main branch are on different submodule commits.

Any easy fix I found was to reset my branch to match what is on main. (This is safe for me to do since I am not actively making code changes to the submodule on my branch, I am just frequently pulling in the latest commits from the submodule's parent repo)

git reset origin -- <submodule name>

This should resolve the merge conflict.

Emit answered 13/2 at 22:21 Comment(0)
G
0

The other problem that gives you this error is if you do not have the submodule checked out -- i.e. the directory is empty. (This is also what gives you the commit-id 00000000...) You have to manually "git clone submodule-repository-URL directory", because all the git commands that should do that for you refuse to do it to an unmerged commit... THEN if you "git add" the directory you can complete the merge.

Girhiny answered 20/2 at 16:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.