Tagging in Git
Just like branches, tags are a way to mark a certain point in time in the life of your repository. Many software projects use them to take snapshots of specific versions of the application for release.
Unlike branches, tags don’t change after they’re created. You don’t check out a tag and continue to work on it. However, you do check out a branch and work on it. It’s easiest to think of tags as snapshots — caught in a moment in the life of the repository — of the project for major milestones, like releases.
They are handled similarly as they are in other version control sytems.
Two Types of Tags #
There are types of tags in Git: annotated and non-annotated. The names say it all: one type let’s us tag with an annotation on what the tag is about, while the other is tag without annotation. Both, however, are tags and mark a point of time in the life of the repository.
Annotated Tags
Annotated tags are created with a message so there’s some context — other than the name of the tag — to go with the tag.
$ git tag v1.2.0 -m "version 1.2.0, including new API"
In addition to the message, annotated tags also include the name of the tagger, and the date the tag was created.
If we run
$ git show v1.2.0
we will get something like this above the list of changes:
tag v1.2.0
Tagger: Ryan Irelan <[email protected]>
Date: Tue Jan 27 14:06:02 2015 -0600
version 1.2.0 of the site
Non-annotated Tags
Non-annotated tags are created without a message, so the only hint as to what the tag is about is how you name it.
$ git tag v1.2.1
Non-annotated tags will look like a commit object, showing the changes made to the repository, but it won’t have metadata about the tag.
Signing Tags #
You can also sign tags to verify their authenticity. Signing a tag uses GPG and you can tie the authentication to the default email address of the user creating the tag or by passing in a GPG key.
Signing tags with GPG will require that you have GPG installed.
Let’s sign a tag using the key of the default email address:
git tag v 1.2.2 -s
You might be prompted for your GPG passphrase and then the tag will be created and signed. Viewing the tag will show your PGP signature.
tag v1.2.2
Tagger: Ryan Irelan <[email protected]>
Date: Tue Jan 27 14:26:29 2015 -0600
v1.2.2
-----BEGIN PGP SIGNATURE-----
iQIcBAABCgAGBQJUx/STAAoJEMgD7XNxH0eBq8UP/iEvCPimWQvdcOwB9mfbIjjV
I+R9DLBvckNAY9RvqToPS/USIVW4GAJzEDyuzZlfILTPLwEEtgO2oWashka3VIAU
Ea98k4002C6263XYaI74mipcVhulPhtUiFO/sCJawz8BYzNFgbtMIrkz8IpqXAML
f2du0ETQPvu+dBbd5yGJIiesRgScZS/QR2kIBVyWOHtznPSxcJ0KIYoLmLWk0FNv
knguS1unQzjJ4c0ZJelD5zo//t1Fhsduf6gP6NP0ULRDZBUKAfQljNBBs3XD67O2
I50rn0wxi8M8rXEZJCjnce8zcQpSyAbme34iV6CFgJn/hjI7cGL3oY9fS+5iFbkW
V61shrJbBIR4TX2Uete7+FhfoPolUHqlh9aqJoCGX6pLj59pYEtKQoMnDTm5+X+T
etYhgLl7GHeohBaFsuQehJfny6+NOW1OuF9/spryj0WNdtqN9YEpSiSG9OI9rPqO
PdJjY/LE5o6ti3ocQP6WrIy+/cgKQAwHBU252B12kSCoNbiQgP/0shw9ZElBeL3H
U3k31EtQPNBLY2gd1qrQYh6CQQAyAr3jy4ELwAju8qIIdKxEO43J7IgN0E2wKzKH
xB+Cr8saV6tLd6pJUFsYSqHEKcMrnyhzYqCFmp1McMkudzb9P80SV7hBSPfaLQTy
AylHzbj0mxbx2yYwy5Sj
=q09K
-----END PGP SIGNATURE-----
Why would you want to sign your tags with GPG?
It’s all about verification that the person who created the Git tag is who they say they are. For your own internal projects, where the repository is private, this might not seem as pressing of a concern. However, for open source software, that is widely distributed online, it’s important that the version I download (many times the source of the downloads is a tag) is legitimate and official. By signing with a verifiable key, I can verify the person who signed it is who they say they are (like a developer or core committer to the project).
Deleting Tags #
If you create a tag in error or no longer need it, you can easily delete any tag using the -d
option of the tag command. You need to specify the tag name so Git knows which tag to delete.
$ git tag -d v1.2.2
After the tag is deleted Git will return a confirmation message.
Re-tagging #
Sometimes you create a tag but at the wrong commit and you need to redo the tag. You could delete the tag and then recreate it but you can also re-tag using the -f
option.
$ git tag -f v1.2.2
Pushing Tags to a Remote #
Tags aren’t automatically pushed to a remote repository when you push a branch. We need to do it explicitly. There are a couple options for doing this.
First, you can do a special push just for one tag:
$ git push origin v1.2.2
This will push just the tag named v1.2.2
to the origin remote.
The other way is to push all tags when you push a branch to a remote.
$ git push --tags
This is less than ideal than because it pushes all of the tags you have. With every collaborator on a project pushing all of their tags, the repository could become cluttered with tags that have no business shared among the team.
I would suggest sticking with the explicit method so you are only ever pushing tags that you really want on the remote repository.
Tags Innards #
As you grow more experienced with Git, it’s also important (and handy when troubleshooting) how Git is storing the tags you create.
Where are tags stored in our Git repository? Let’s find out.
First, we’ll cd
into the .git
directory at the root of our project.
cd .git
And then list the files and directories to see we have.
ls
Then we’ll move into the refs
directory, which is where Git stores the references to the tags we create (remember, tags are simply references to a commit, so there’s no extra data stored in a tag).
Inside of refs
we navigate to tags
. When list out the contents (using ls
), we see the tags we’ve created.
v1.1 v1.2 v1.2.2
These tags are all files that contain the reference to a commit (in the form of the commit’s SHA).
Every time we create a new tag, Git creates a new tag file in the refs/tags
directory as a way of keeping track of the tags in this repository.