From git submodule --help
, HEAD detached is the default behavior of git submodule update --remote
. This has nothing to do with which branch is being tracked in a submodule.
For anyone only want a solution, jump to the 2nd part directly.
Reason
We need to understand what a submodule is.
Submodule is a way to include another project into your current project. It's not really adding these files into the commit history of your main project, but by referring a snapshot (commit) of the submodule.
Quote from Starting with Submodules section in book Pro Git
Although submodule DbConnector
is a subdirectory in your working directory, Git sees it as a submodule and doesn’t track its contents when you’re not in that directory. Instead, Git sees it as a particular commit from that repository.
Every commit of a repo is a snapshot/state of your code at that time. The state of submodule at that time has to be deterministic too. You can't say in this commit, I include the master (or another) branch of another repo. You have to specify the state of submodule by a commit id.
Including another repos as a submodule is basically
git clone uri://another-repo path/to/submodule
cd path/to/submodule
git checkout <commit-id>
# git submodule system will add the reference commit id but not the files
When anyone uses your repo with submodule, it will clone the submodule and checkout
the specified commit as well.
And checking out a commit results HEAD detached. Why did my Git repo enter a detached HEAD state?
Solution
If you want the submodule merged with remote branch automatically, use --merge
or --rebase
.
man git-submodule
--merge
This option is only valid for the update command. Merge the commit recorded in the superproject into the current branch of the submodule. If this option is given, the submodule's HEAD will not be detached.
--rebase
Rebase the current branch onto the commit recorded in the superproject. If this option is given, the submodule's HEAD will not be detached.
If your submodule has already been detached, fix the detached state before using following 2 solutions.
cd path/to/submodule
# Assuming you're tracking the 'master' in the submodule
git checkout master
Solution 1: Use options in command line
# cd back to project root
git submodule update --remote --merge
# or
git submodule update --remote --rebase
Recommended alias:
git config alias.supdate 'submodule update --remote --merge'
# do submodule update with
git supdate
Solution 2: Add options into config file
Another solution is to change submodule update behavior in the gitmodule
file by by setting submodule.$name.update
to merge
or rebase
.
It basically means you can do git submodule update --remote
without passing --merge
or --rebase
explcitly, but read from config file automatically.
Here's an example about how to config the default update behavior of submodule update in .gitmodule
.
[submodule "bash/plugins/dircolors-solarized"]
path = bash/plugins/dircolors-solarized
url = https://github.com/seebi/dircolors-solarized.git
update = merge # <-- this is what you need to add
Or configure it through command line,
# replace $name with a real submodule name
git config -f .gitmodules submodule.$name.update merge
Others
Adding a branch
option in .gitmodule
is NOT related to the detached behavior of submodules at all. The old answer from mkungla is incorrect, or obsolete.
Let's make it clear there's no need to specify a branch to be tracked. origin/master
is the default branch to be tracked.
--remote
Instead of using the superproject's recorded SHA-1 to update the submodule, use the status of the submodule's remote-tracking branch. The remote used is branch's remote (branch.<name>.remote
), defaulting to origin
. The remote branch used defaults to master
.
References