Git submodules


Git submodules. I mean, it’s not bad. It could use a bit of sugar though. Case in point: tracking releases, rather than commits to master or main. Even if we can assume that most project use tags and semver nowadays, git submodules point to a commit hash, and nothing else, so you can’t quickly see to what version tag, if any, you’ve pinned your submodules to. The best incantation I’ve found is git describe HEAD --tags, but you have to know that, when not checked out at a commit that is tagged, git will generate something like v0.5.2-80-g9ea9eff7, where v0.5.2 is the nearest tag ancestor, 80 the number of commits since that ancestor, g doesn’t seem to mean anything in particular, and 9ea9eff7 the short hash of the current commit. If your currently checkout out at a tag, say v0.5.2, it will show just that. You see? If you know how to interpret that output, with git submodule foreach you can get a sitrep on your submodules' status.

Then, auto-updating to the last tag. Can we do that? git describe --abbrev=0 --tag strips the above to the name of the nearest tag ancestor. So if you want to get to the latest release, the best I could manage is to actually pull up to the latest commit in all submodules (git submodule update --remote), and then use this beauty to checkout the last tagged commit: git submodule foreach 'git checkout `git describe --abbrev=0 --tags`'.

Unfortunately, that doesn’t check what the latest tagged commit is, it actually checks out at that commit. Since submodules upgrades may require adaptations in your code, this is probably not what you want, you’d like to update them one by one and include your adaptations in the change. I don’t know why, but for the old copy of a repo that I’ve been working on for the past year, it is actually required to checkout the latest updates, merely fetching the remote and investigating the last commit there does not work.

It does on a fresh clone, so maybe in the old repo git is in a certain state, which I have no idea of how to troubleshoot. In any case, if you want to know the latest tag for fresh clone:

git submodule foreach 'git fetch'
git submodule foreach 'git describe `git log --branches -1 --pretty=format:"%H"` --tags --abbrev=0'