Git submodule is in "detached head" state after cloning and submodule update
A submodule is always checked out as a detached HEAD (see "Why did git detach my head?"), since the index of the parent repo contains only the SHA1 as a special entry in its index, as explained by Gary Fixler's answer.
Even if you configure your submodule to follow a branch (or convert an existing submodule to follow a branch), a git submodule update --remote
would checkout the latest SHA1 of that remote branch, but the result would by default be a detached HEAD.
Only by adding --merge
or --rebase
to that command (git submodule update --remote (--merge/--rebase)
) would you get a non-detached HEAD, as seen in Simba's answer): by default, the master
branch.
If you don't update that way (git submodule update --remote (--merge/--rebase)
), then you need to go in that submodule and make a branch yourself there.
If you want to contribute to said submodule (making new commits in it), it is a good idea to create a new branch.
cd mySubmodule
git checkout -b aNewBranch
# work
git add .
git commit -m "new commits"
git push -u origin aNewBranch
# record the new submodule state in the parent repo:
cd ..
git add mySubmodule
git commit -m "new state of mySubmodule"
git push
Note for Git 2.16 (Q1 2018): "git checkout --recursive
" may overwrite and rewind the history of the branch that happens to be checked out in submodule
repositories, which might not be desirable.
Detach the HEAD
but still allow the recursive checkout to succeed in such a case.
See commit 57f22bf (28 Jul 2017), and commit 3ef2538 (24 Jul 2017) by Stefan Beller (stefanbeller
).
(Merged by Junio C Hamano -- gitster
-- in commit 0b75572, 06 Dec 2017)
recursive submodules: detach HEAD from new state
When a submodule is on a branch and in its superproject you run a recursive checkout, the branch of the submodule is updated to what the superproject checks out.
This is very unexpected in the current model of Git as e.g. 'submodule update
' always detaches the submodule HEAD.Despite having plans to have submodule HEADS not detached in the future, the current behavior is really bad as it doesn't match user expectations and it is not checking for loss of commits (only to be recovered via the reflog).
Detach the HEAD unconditionally in the submodule when updating it.
The contents of git directories are stored in simple text file manifests (i.e. directory listings) called "trees" that look like the following, where blobs are the contents of files, and trees are yet more trees like this one:
100644 blob 0c31be662540ce902cee106f86bfdeef519fc662 .gitignore
100644 blob 1d364edf530c2238e79162bf2d9f30c2af610347 .gitmodules
040000 tree fc6bc39202ec20228e9135cd426110c558b625cd foo
040000 tree 2f9fc460f3a2370ed45b39b2bcaaf9b6e746b823 bar
If bar was a submodule, instead of merely a directory, however, the tree containing it would be listed like this:
100644 blob 0c31be662540ce902cee106f86bfdeef519fc662 .gitignore
100644 blob 1d364edf530c2238e79162bf2d9f30c2af610347 .gitmodules
040000 tree fc6bc39202ec20228e9135cd426110c558b625cd foo
040000 commit 2f9fc460f3a2370ed45b39b2bcaaf9b6e746b823 bar
Note that instead of bar being a tree, it's now a commit (in a submodule). This is all git stores about a submodule at the tree/commit level, so it can't know what branch a commit was on. In fact, storing branch names can't work. They can change. Also, if you check out an old commit in your repo that needs to roll the submodule back as well, should the branch move back in the submodule? That would cast the commits after that new branch location into unreferenced territory.
The branches are for humans to use, to make sense of the DAG, and where particular lines of thought are. Git doesn't care how we refer to the commits. It needs a concrete location so you can safely move the containing repo around, and know that the submodule will always be checked out to where it was at that time. The only truth is the hash.