Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know if a Git tag has been moved?

Tags:

git

git-tag

I used git tag --force to move a tag, and now I want to know where was the tag before I move it.

I didn't find anything in the manual pages nor on the website Pro Git § 2.6 Git Basics - Tagging.

Nobody seems to have posted this question before.

like image 790
Darth Avatar asked Aug 07 '14 17:08

Darth


People also ask

Can git tags be moved?

When a new release is made it can be tagged with a semantic version such as v1. 4.3 , and the major tag v1 can then be moved ahead to point to the same commit.

Are git tags automatically pushed?

From the docs: Setting this value to --no-tags disables automatic tag following when fetching from remote . Setting it to --tags will fetch every tag from remote , even if they are not reachable from remote branch heads.

How do I know if my tags are annotated?

If the tag is an annotated tag, you'll see the message and the tag object, followed by the commit. If the tag is a lightweight tag, then you'll see only the commit object. If the current commit exactly matches that of a tag, then only the tag name is printed.


1 Answers

The only way to know for sure is to have kept tabs (tags?) on the tag before-hand.

As noted in comments, there are two kinds of tags: "annotated" and "lightweight".

In both cases, for a tag named T, git creates a reference named refs/tags/T. For a lightweight tag, this name points directly to some commit. For an annotated tag, git first creates an "annotated tag" object in the repository (this is stored in the same way as a commit, tree, or blob), and then has the reference name—which would otherwise just be a "lightweight tag"—point to the annotated tag object. The annotated tag object then points to the next link in the chain, normally a commit object.

When updating a reference, git checks the logs directory (normally .git/logs) to see if there's a file available corresponding to the ref-name. If you peek into .git/logs you'll see a file named HEAD and a directory named refs. Underneath refs, there's a directory named heads, and under refs/heads there is a file for each branch. The refs/heads/master file contains the reflog for branch master, for instance.

By default, there is no .git/logs/refs/tags directory, hence there's no file for a tag and hence there's no reflog for tag updates. This is because tags are not intended to move. They're supposed to be permanent; that's the main property that's different between a tag-name and a branch-name: branch-tips move, tags don't.

However, if you intend to move a tag, and then want to know where it used to be, you can create .git/logs/refs/tags and then make a file in there containing the tag-name. Once you have done that, tag updates will write a reflog entry. Obviously this only helps if you plan this in advance.

There is one other direct way to recover "where a tag used to point": find an old record of the tag's SHA-1 value. That's what a reflog would do, but if you don't have one, maybe you have a clone of the repository, and maybe that clone has the old tag. Or you might get lucky and have a window where the SHA-1 is still shown in the scrollback, for instance.


If the tag was an annotated tag, you can search the repository for annotated tag objects that no longer have a reference, using git fsck. This will generally produce a lot of output. "Dangling blobs" are quite normal in an active repository, they occur when you git add something and then git add a different version before committing.
"Dangling commits" occur when commits get abandoned and their reflog entries expire. The thing to look for here is a "dangling tag":

dangling tag 20e14672ee2253d38c1001179d8f17688d47059c

This will be the SHA-1 of the annotated tag object; you can attach a new reference (such as a new lightweight tag, or re-force the old one or whatever) to make sure it won't get git gc-ed and removed.

like image 57
torek Avatar answered Oct 16 '22 00:10

torek