We are using tags in our build, so it is possible to see which tag a specific SW stems from. Furthermore we add some information in the tag like revision and date to help technicians in the field.
Since we have several products build on a shared platform, it happens that several tags are put on the same commit.
If I have e.g. 3 tags on the same commit and I checkout a specific tag (git checkout <tag_1>) both git (git bash) and (git) describe will only show the last entered tag (tag 3) which is then injected to the release. This means that product 1 will get a tag for product 3, even though I checkout on the tag for product 1?
Is it possible to checkout a specific tag on the commit so that is the one shown?
CodePudding user response:
As Lasse V. Karlsen noted in a comment, Git doesn't save the identity of the tag name used to select some particular commit, just the hash ID of that commit. So in general, if you have more than one tag that names one commit, there's no unique reverse mapping from hash ID to tag and Git can't tell you how you got here.
The HEAD
reflog does contain the necessary information as a sort of a comment, but reflogs are not entirely reliable. In particular, they can be turned off, or the entries can expire. There is also no promise that this will be true in the future, or that the format will remain the same.
If you have control of the build process, you can simply save the tag name you use (or it uses) to do the git checkout
or git clone
or git switch
or whatever step. Then, instead of running git describe
or similar to find the tag, just use the saved name. In short, if you supplied it, you can remember it.
Of course, sometimes things are not this simple: you did supply it, but to commercial (or free) software X, and the build server is commercial (or free) software Y, and X and Y refuse to talk to each other, so that you cannot deliver the tag name from X to Y. Furthermore software Y insists on using git describe
(only). In this case you have several remaining remedies:
Delete, from the repository on which you're doing the build, the irrelevant tags that
git describe
might use. Since we often use temporary clones for the build process, then destroy the temporary clone, this might be easy to do and damage nothing.Make sure you never re-use a tag for one commit.
The latter is easy enough to do. It just requires a bit of care and one trick. A Git commit represents a state: an author, a committer, a timestamp, a log message, and other metadata, plus a snapshot.
A tag name holds a Git object ID: that of a tag object (an annotated tag), or that of a commit. When the name holds the ID of a tag object, the tag object holds, or otherwise resolves to, a commit hash ID, and it's this commit that git checkout
or git switch --detach
ends up using:
git checkout v1.2
resolves the name v1.2
to an object ID, and if that's a tag object, follows the tag objects until it arrives at a commit object. Whatever hash ID it gets at that point is the commit that becomes your detached HEAD.
We need that commit hash ID to uniquely map back to one tag name or object. That can only happen if there's only one such tag. So if we need to tag the same snapshot again, we have to duplicate the snapshot.
But that's easy! If we have some commit, say 96800d2
for short, and we need to make a duplicate of it to tag again, we just check it out by hash ID or tag name, then run git commit
to make a new commit for our new tag. There's just one hitch, illustrated here along with the way around it:
$ git checkout t1
[snippage]
HEAD is now at 96800d2 Initial commit
$ git commit -m "duplicate t1 for t2"
HEAD detached at t1
nothing to commit, working tree clean
$ git tag
t1
$ git commit --allow-empty -m "duplicate t1 for t2"
[detached HEAD 4e69364] duplicate t1 for t2
$ git tag -m "new tag t2 for release purposes, same as t1" t2
$ git tag
t1
t2
Our new tag t2
exists now and tags commit 4e69364
, not 96800d2
. The two commits contain identical snapshots but different metadata, and git log
shows us why we have the extra commit:
$ git log --all --decorate --oneline --graph
* 4e69364 (HEAD, tag: t2) duplicate t1 for t2
* 96800d2 (tag: t1, main, branch-y, branch-x) Initial commit
As desired, git describe
now describes this as t2
.
CodePudding user response:
I found the answer in another question someone else referred me to. git describe with two tags on the same commit
This method fixed my problem :-) using
git tag -l | grep [product_name] | tail -1
I got the latest tag with the product name.