Juan
Juan

Reputation: 1371

how do I track the history of an annotated git tag?

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

Answers (3)

VonC
VonC

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

mb-lang
mb-lang

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

Schwern
Schwern

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

Related Questions