How does git submodule add -b
work?
After adding a submodule with a specific branch, a new cloned repository (after git submodule update --init
) will be at a specific commit, not the branch itself (git status
on the submodule shows "Not currently on any branch").
I can't find any information on .gitmodules
or .git/config
about the submodule's branch or any specific commit, so how does Git figure it out?
Also, is it possible to specify a tag instead of a branch?
I'm using version 1.6.5.2.
An example of how I use Git submodules.
And that looks a little bit like this:
Maybe it helps (even though I use a tag and not a branch)?
We use Quack to pull a specific module from another Git repository. We need to pull code without the whole code base of the provided repository - we need a very specific module / file from that huge repository and should be updated every time we run update.
So we achieved it in this way:
Create configuration
With the above configuration, it creates one directory from the provided GitHub repository as specified in first module configuration, and the other one is to pull and create a file from the given repository.
Other developers just need to run
And it pulls the code from the above configurations.
Note that if you have an existing submodule which isn't tracking a branch yet, then (if you have git 1.8.2+):
Make sure the parent repo knows that its submodule now tracks a branch:
Make sure your submodule is actually at the latest of that branch:
(with 'origin' being the name of the upstream remote repo the submodule has been cloned from.
A
git remote -v
inside that submodule will display it. Usually, it is 'origin')Don't forget to record the new state of your submodule in your parent repo:
Subsequent update for that submodule will have to use the
--remote
option:Note that with Git 2.10+ (Q3 2016), you can use '
.
' as a branch name:If you want to update all your submodules following a branch:
Note that the result, for each updated submodule, will almost always be a detached HEAD, as Dan Cameron note in his answer.
(Clintm notes in the comments that, if you run
git submodule update --remote
and the resulting sha1 is the same as the branch the submodule is currently on, it won't do anything and leave the submodule still "on that branch" and not in detached head state.)To ensure the branch is actually checked out (and that won't modify the SHA1 of the special entry representing the submodule for the parent repo), he suggests:
Each submodule will still reference the same SHA1, but if you do make new commits, you will be able to push them because they will be referenced by the branch you want the submodule to track.
After that push within a submodule, don't forget to go back to the parent repo, add, commit and push the new SHA1 for those modified submodules.
Note the use of
$toplevel
, recommended in the comments by Alexander Pogrebnyak.$toplevel
was introduced in git1.7.2 in May 2010: commit f030c96.dtmland
adds in the comments:The same command but easier to read:
umläute refines dtmland's command with a simplified version in the comments:
multiple lines:
The only effect of choosing a branch for a submodule is that, whenever you pass the
--remote
option in thegit submodule update
command line, Git will check out in detached HEAD mode (if the default--checkout
behavior is selected) the latest commit of that selected remote branch.You must be particularly careful when using this remote branch tracking feature for Git submodules if you work with shallow clones of submodules. The branch you choose for this purpose in submodule settings IS NOT the one that will be cloned during
git submodule update --remote
. If you pass also the--depth
parameter and you do not instruct Git about which branch you want to clone -- and actually you cannot in thegit submodule update
command line!! -- , it will implicitly behave like explained in thegit-clone(1)
documentation forgit clone --single-branch
when the explicit--branch
parameter is missing, and therefore it will clone the primary branch only.With no surprise, after the clone stage performed by the
git submodule update
command, it will finally try to check out the latest commit for the remote branch you previously set up for the submodule, and, if this is not the primary one, it is not part of your local shallow clone, and therefore it will fail withNote: Git 1.8.2 added the possibility to track branches. See some of the answers below.
It's a little confusing to get used to this, but submodules are not on a branch. They are, like you say, just a pointer to a particular commit of the submodule's repository.
This means, when someone else checks out your repository, or pulls your code, and does git submodule update, the submodule is checked out to that particular commit.
This is great for a submodule that does not change often, because then everyone on the project can have the submodule at the same commit.
If you want to move the submodule to a particular tag:
Then, another developer who wants to have submodule_directory changed to that tag, does this
git pull
changes which commit their submodule directory points to.git submodule update
actually merges in the new code.In my experience switching branches in the superproject or future checkouts will still cause detached HEADs of submodules regardless if the submodule is properly added and tracked (i.e. @djacobs7 and @Johnny Z answers).
And instead of manually checking out the correct branch manually or through a script git submodule foreach can be used.
This will check the submodule config file for the branch property and checkout the set branch.
git submodule foreach -q --recursive 'branch="$(git config -f <path>.gitmodules submodule.$name.branch)"; git checkout $branch'