cDreamer
cDreamer

Reputation: 415

Git Submodule is Not Updating to Correct Commit

I have a parent repository that has a submodule within it. If I look on the remote side, I can see that the commit ID pointed to by the submodule is 862e0c4e. This was recently updated to point to that commit ID.

I have a local copy of this parent repository with the submodule already checked out. However my local copy of the parent repository is old and thus the submodule checked out is pointing to a different commit ID. If I run git status on the submodule on my local copy then it outputs the following: HEAD detached from 475d0b3. This is understandable since this is an old copy of the repository.

I have already set my git config parameter submodule.recurse to true, so my expectation is that if I run git pull on the parent repository, it will pull all the changes made to the parent repository, including checking out the correct version of the submodule. However after I run git pull on the parent repository, the submodule does not change. It continues to point to the old commit ID.

I also tried running the command git pull --recurse-submodules. No change though, as the submodule continues to point to the old commit ID.

If I run git submodule update --init, then the submodule will check out the correct version and the commit ID will be updated.

Is my expectation of setting submodule.recurse=true incorrect? Is there no way for the submodule to update the commit ID it's pointing to automatically when running git pull?

Upvotes: 0

Views: 3127

Answers (1)

torek
torek

Reputation: 488193

Submodules are always in detached-HEAD mode. Well ... not always always, but that's entirely normal. To get the superproject Git to update the submodule Git—i.e., to pick a new commit hash ID for detached HEAD mode in the submodule—you must convince the superproject Git that it is time to:

(cd sub/module && git switch --detach <hash>)

The hash ID provided here is stored as what Git calls a gitlink, in each commit in the superproject. You can see this gitlink in git ls-files --stage output for instance.

The submodule.recurse=true or git pull --recurse-submodules flags work by noticing if and when the gitlink hash ID changes in the superproject's index / staging-area. If and when this hash ID changes, the superproject Git will do the:

(cd sub/module && git switch --detach <new-hash>)

operation. Otherwise, it won't. Among other things, this means that once you have updated the superproject itself without updating the submodule (so that the hash ID stored in the index matches that in a newer commit, but not that checked out in the submodule), no further "update the superproject" operation results in a change, unless the update brings in a new commit with yet another new stored hash ID.

The git submodule update command is an explicit way to have the superproject Git go through the current commit / index, find all the gitlinks therein, and run the same kind of command, with the chosen hash ID, in each submodule. So, manually running it does the trick.

Note that adding --remote to git submodule update changes where the superproject gets a hash ID. The rest of the process is unchanged: the superproject Git still pokes along through the index, looking for gitlinks. But, having found a gitlink for sub/module, the superproject Git doesn't read the hash ID from the gitlink. Now, instead, it does:

(cd sub/module && git fetch)

which causes the submodule repository to be updated from its remote, and then:

(cd sub/module && git rev-parse <branch-name>)

where the branch-name part comes out of the branch setting for that submodule. The branch setting comes from .git/config, if present, or from .gitmodules if not. Only the git submodule update command actually does this; the --recurse or recurse=true options never do that.

As you're seeing, submodules are pretty brittle. People sometimes call them sob-modules, for good reason. There are numerous workarounds, including the repo scripts that Google wrote; none are really satisfactory.

Upvotes: 1

Related Questions