Reputation: 1371
How do I view the history of a tag in git? For instance, let's suppose that it was decided that tag 't1' was pointing at the wrong commit after it has been pushed to other repositories. One can change the tag - git tag -a -f t1 [commitid]
. git show t1
will show the information for the tag (annotation & what commit it currently points to). But how does one show the commits it may have pointed to in the past?
Note: This is a more general version of See who deleted git tag. There is an incantation in an answer for that question that uses git fsck
and git show
to allow one to get at "unreachable" commits assuming garbage collection has not reaped them.
Upvotes: 2
Views: 1787
Reputation: 1324258
First, moving a tag around is first a local operation (that you can track, for up to 90 days) in git reflog
.
(As noted by Guildenstern in the comments, setting core.logAllRefUpdates
to always
would force a missing reflog to be automatically created for any ref under refs/
)
As long as the tag was not pushed, you can move it as many times as you need.
Once pushed, though, it should be considered immutable.
Which means if "It is [typically] a mistaken or premature tag that is intended to be a pointer to a particular commit, but needs to be moved", then, if it was pushed, you need to create a new tag.
For example, for a mistakenly applied 1.1.0
tag: create a 1.1.1
tag instead of the initial 1.1.0
.
And publish a 1.1.0_deprecated
on the commit currently referenced by 1.1.0
to better communicate that the 1.1.0
tag should not be considered.
Upvotes: 4
Reputation: 93
If you want an audit log for all tag changes, you can tell git to keep one:
git config --global core.logallrefupdates always
Afterwards, git will start keeping track of all changes to all tags in the reflog. To find out why a tag was moved or deleted and where it previously pointed, you can then simply query the reflog:
git reflog mytagname
Note that - at least by default - this history will not be kept around forever, as it is subject to the usual reflog expiration rules. You can prevent that by changing the following options:
So, contrary to the other answers, what you want is definitely possible. (With a few limitations, such as that the reflog is local to each clone, which means that you will not have a consistent, shared history of your tags.)
I also believe that the philosophical debate on whether you should do this is unnecessary. While git tags certainly weren't designed to be moved around, I've also run into scenarios where I needed exactly that, and having an audit log for each tag for debugging purposes makes sense even if you never intend to move them.
Upvotes: 2
Reputation: 164809
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 <[email protected]> 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.
Upvotes: 1