Actually, even with the -b
option, Git submodules always specify a specific commit by raw hash ID. The -b
option is notable for how Git doesn't really use it, in other words.1 ?? But it's not what you want anyway: you want a specific tag.
Now, the thing about a Git tag is this: it's never supposed to move. What that means, once it's stripped down to bare-bones ideas, is that a tag name is just a human-readable name for some specific raw hash ID, and it should always mean that hash ID. This distinguishes tag names from branch names: branch names are names for a specific hash ID, but the hash ID for the name br1
, with br1
being a branch name, is supposed to change over time.
Another way to phrase this is:
A branch name always means the latest commit, rather than one particular commit regardless of what's happened recently.
A tag name always means that one particular commit we picked out on that particular day. In essence, this is the opposite of a branch name.
But, given the above, and given the way submodules work—the superproject specifies the submodule commit by raw hash ID—there's no point in using a tag name. If tag name tag1
means commit a123456
forever, then the only reason to use the name tag1
instead of the raw hash ID is for human consumption ... and a submodule reference isn't for human consumption, it's for Git. So you just want to pick a commit and stick with it, which is what a submodule already does.
In other words, don't bother. The only time this would make any difference is if you move tags, and you're not supposed to move tags. If you are moving tags—picking a different commit now and then—you're misusing them: the things that are supposed to move are branch names, not tag names. Stop doing that.2
1Obviously, Git does record the branch name somewhere. You can then get Git to use it. The method is not obvious, though, and git submodule update
is a little weird with it. The real key here is that the superproject Git repository keeps the submodule repository on a detached HEAD at all times. Even if you specify a branch name, the submodule is still using detached-HEAD mode. So it's not actually using the branch name—not directly, anyway. The idea, not necessarily terribly well implemented, is that the superproject Git can command the submodule Git to git fetch
from some third Git repository, then use git rev-parse
to translate some remote-tracking name related to the branch name into a hash ID, and thereby somehow arrive at the right hash ID to use for the detached HEAD checkout in the submodule.
This is all rather cumbersome and complicated. Submodule support is being improved as an ongoing project, and it might someday become simpler and saner, but for now my personal recommendation is that if you want branch-like behavior from "submodules", don't use git submodule
itself directly here. Just enter the submodule, treat it as a regular Git repository, run git checkout
or git switch
as usual, and then do your work there to bring it up to date and have the right commit checked out. Then, exit the submodule back to the superproject, and use git add
to update the superproject repository's index so as to record the new correct hash ID.
If you do all this my way, you don't need the -b
option at all. You can use it as a reminder-to-self, if you like.
If you have a sufficiently modern Git, git submodule update --remote
can simplify this somewhat. I know this didn't work well in Git 1.5/1.6; it might be OK as far back as 1.7 or 1.8, which would make it work fairly well today, since even the older Linux distributions now come with 1.7 or 1.8 versions. It's probably fine since about 2.5, about the time git worktree
appeared.
2Of course, with Git, you are in control. If you have a really damn good reason to move tags around, and are aware of how it can break the heads of other people who are using your repository, you can in fact move tags around. But then you'll need to move the submodule commits around by making new commits. See also footnote 1.