How do I view the history of a tag in git?
You can't, it does not exist.
Lightweight tags and branches are labels which point at a commit. Each is a single file on disk or line in a packfile with a name and the commit ID it points to. They have no history. When a tag is moved or a branch updated the file or line is overwritten.
Annotated tags work the same way, but they have a name and the ID of a tag object. A tag object holds the tag name, annotation and the commit it points at. git tag -a -f
makes a new tag object and changes the file/line to point at the new tag object. There is no history.
Here's what is inside an unreachable tag object.
$ git fsck --unreachable | grep tag
Checking object directories: 100% (256/256), done.
Checking objects: 100% (3/3), done.
unreachable tag f25f9e059dc07f741aae47ee422f675b9bdd0f5f
$ openssl zlib -d < .git/objects/f2/5f9e059dc07f741aae47ee422f675b9bdd0f5f
tag 153object 91e645c1a8a2ff1edc788066ef02f349f959da20
type commit
tag annotated
tagger Michael G. Schwern <schwern@pobox.com> 1620501711 -0700
test annotated
It points at commit 91e645c. It was tagged by me today. The annotation is "test annotated".
As you noted it is possible, on the repository which moved the tag, to find unreferenced tag objects assuming they have not yet been garbage collected. git fsck --unreachable | grep tag
This is only an emergency operation to recover after a mistake and should not be part of normal procedure. Backups are a better option.
It happens all the time in the real world that developers move tags before an official release is generated.
Then they are using tags wrong. The sole purpose of tags is to not move. Tags which move are branches. Use a branch instead.
For example, perhaps you have a release
tag which you move every time you release a new version. Replace this with a branch called release
. They are functionally equivalent, but a release branch is supposed to move.
A release branch still doesn't have a history. If you want a release history that is what tags are for. Tag each release like v1.0.0
, v1.0.1
, v1.1.0
and so on. If the tag is wrong and has already been pushed don't change the tag, declare a new release.