Tagging in Git

Just like branch­es, tags are a way to mark a cer­tain point in time in the life of your repos­i­to­ry. Many soft­ware projects use them to take snap­shots of spe­cif­ic ver­sions of the appli­ca­tion for release.

Unlike branch­es, tags don’t change after they’re cre­at­ed. You don’t check out a tag and con­tin­ue to work on it. How­ev­er, you do check out a branch and work on it. It’s eas­i­est to think of tags as snap­shots — caught in a moment in the life of the repos­i­to­ry — of the project for major mile­stones, like releases. 

They are han­dled sim­i­lar­ly as they are in oth­er ver­sion con­trol sytems.

Two Types of Tags #

There are types of tags in Git: anno­tat­ed and non-anno­tat­ed. The names say it all: one type let’s us tag with an anno­ta­tion on what the tag is about, while the oth­er is tag with­out anno­ta­tion. Both, how­ev­er, are tags and mark a point of time in the life of the repository.

Anno­tat­ed Tags

Anno­tat­ed tags are cre­at­ed with a mes­sage so there’s some con­text — oth­er 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 addi­tion to the mes­sage, anno­tat­ed tags also include the name of the tag­ger, and the date the tag was created.

If we run 

$ git show v1.2.0

we will get some­thing 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-anno­tat­ed Tags

Non-anno­tat­ed tags are cre­at­ed with­out a mes­sage, so the only hint as to what the tag is about is how you name it.

$ git tag v1.2.1

Non-anno­tat­ed tags will look like a com­mit object, show­ing the changes made to the repos­i­to­ry, but it won’t have meta­da­ta about the tag. 

Sign­ing Tags #

You can also sign tags to ver­i­fy their authen­tic­i­ty. Sign­ing a tag uses GPG and you can tie the authen­ti­ca­tion to the default email address of the user cre­at­ing the tag or by pass­ing in a GPG key.

Sign­ing 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 prompt­ed for your GPG passphrase and then the tag will be cre­at­ed and signed. View­ing 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 ver­i­fi­ca­tion that the per­son who cre­at­ed the Git tag is who they say they are. For your own inter­nal projects, where the repos­i­to­ry is pri­vate, this might not seem as press­ing of a con­cern. How­ev­er, for open source soft­ware, that is wide­ly dis­trib­uted online, it’s impor­tant that the ver­sion I down­load (many times the source of the down­loads is a tag) is legit­i­mate and offi­cial. By sign­ing with a ver­i­fi­able key, I can ver­i­fy the per­son who signed it is who they say they are (like a devel­op­er or core com­mit­ter to the project).

Delet­ing Tags #

If you cre­ate a tag in error or no longer need it, you can eas­i­ly delete any tag using the -d option of the tag com­mand. You need to spec­i­fy the tag name so Git knows which tag to delete.

$ git tag -d v1.2.2

After the tag is delet­ed Git will return a con­fir­ma­tion message.

Re-tag­ging #

Some­times you cre­ate a tag but at the wrong com­mit and you need to redo the tag. You could delete the tag and then recre­ate it but you can also re-tag using the -f option.

$ git tag -f v1.2.2

Push­ing Tags to a Remote #

Tags aren’t auto­mat­i­cal­ly pushed to a remote repos­i­to­ry when you push a branch. We need to do it explic­it­ly. There are a cou­ple options for doing this.

First, you can do a spe­cial push just for one tag:

$ git push origin v1.2.2

This will push just the tag named v1.2.2 to the ori­gin remote.

The oth­er way is to push all tags when you push a branch to a remote. 

$ git push --tags

This is less than ide­al than because it push­es all of the tags you have. With every col­lab­o­ra­tor on a project push­ing all of their tags, the repos­i­to­ry could become clut­tered with tags that have no busi­ness shared among the team.

I would sug­gest stick­ing with the explic­it method so you are only ever push­ing tags that you real­ly want on the remote repository.

Tags Innards #

As you grow more expe­ri­enced with Git, it’s also impor­tant (and handy when trou­bleshoot­ing) how Git is stor­ing the tags you create.

Where are tags stored in our Git repos­i­to­ry? Let’s find out.

First, we’ll cd into the .git direc­to­ry at the root of our project.

cd .git

And then list the files and direc­to­ries to see we have.

ls

Then we’ll move into the refs direc­to­ry, which is where Git stores the ref­er­ences to the tags we cre­ate (remem­ber, tags are sim­ply ref­er­ences to a com­mit, so there’s no extra data stored in a tag).

Inside of refs we nav­i­gate to tags. When list out the con­tents (using ls), we see the tags we’ve created.

	v1.1    v1.2    v1.2.2

These tags are all files that con­tain the ref­er­ence to a com­mit (in the form of the commit’s SHA). 

Every time we cre­ate a new tag, Git cre­ates a new tag file in the refs/tags direc­to­ry as a way of keep­ing track of the tags in this repository.