Tagging is a very popular and common concept in version control systems. Tags are generally used to mark special milestones in a history of your repository like releasing a new version of your product. The common practice is to create a tag for every released version of your product so that you can easily switch back to it, see the source code or rebuild.
What is tag?
In Git tag is a named reference to a specific commit in your repository. It is very convenient because you can use user-friendly names for commits instead of remembering or writing down their SHA hashes.
At this point you may notice a similarity to branches because they are also user-friendly names for commits. The difference is that branches can change the commit they point to while tags are immutable and always point to the same commit. As a consequence it is impossible to add any new change to a tag.
Git supports few types of tags. Lightweight tags are the most basic ones because they store only hash of the commit they refer to – nothing else is stored. They can be created by switching to the commit you want to tag and then issuing git tag command with the name of the tag to create:
$ git tag v1.0
Unsigned annotated tags
Lightweight tags have several drawbacks which disqualify them in many situations. They cannot have tag message, creation date, author or optionally cryptographic signature. If you want this kind of information, you can create an unsigned annotated tag by adding -a option:
$ git tag -a v1.1
If you don’t want to be prompted for the tag message, you may provide it on the command line by adding -m option:
$ git tag -a -m 'Release version 1.1' v1.1
Here I would also like to point that if -m or -F file option is given, Git will always create annotated tag so -a may be omitted in this case.
Signed annotated tags
It is also possible to create annotated tag signed using GnuPG program by adding -s option:
$ git tag -s -m 'Release version 1.3' v1.3 You need a passphrase to unlock the secret key for user: "Robert <firstname.lastname@example.org>" 4096-bit RSA key, ID A231EC80, created 2014-03-09
The signed tag can be later verified whether is was created by an authorized person.
By default the signing key is chosen from GnuPG keyring using the default e-mail address but it is also possible to explicitly state the key identifier using -u option:
$ git tag -s -u A231EC80 -m 'Release version 1.4' v1.4 You need a passphrase to unlock the secret key for user: "Robert <email@example.com>" 4096-bit RSA key, ID A231EC80, created 2014-03-09
Once you create several tags, you may want to see the list of them:
$ git tag -l -n10 v1.1 Release version 1.1 v1.3 Release version 1.3 v1.4 Release version 1.4
The command lists all existing tags with maximum 10 lines of their tag message. If the tag is a lightweight tag, the message of the last commit is shown.
Showing tag details
To see more details about specific tag, you may use git show command:
$ git show v1.4 tag v1.4 Tagger: Robert Date: Sun Mar 9 10:44:55 2014 +0100 Release version 1.4 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJTHDgXAAoJEA9AcK2iMeyAO8IP/jaFq+1u6k9Dsd+t6Om2HBDA pttI01tO1X9YdrM/UbUrqAbnMhkgpiJrmVPKwvyl6yObKDGlho1Px2EosHu4g3G0 lhpXQ46JtYmpwc4edxIzLwS+ZhQrF0TKK9smdxiEsqNrln2o/Ce3skl6FrKKsWr1 K83z218dQnNkB8Xx9JdodttghXIwhsGlJsx9qEBseaHHqFAOZlyLnGADh0uKjsVp 0Lbr/WtiWausFMnIPEek1+cXsLrZlEGVkOm6Ja8QVstcw9ZR4/JhErA0Ahl3L4ZW Gxgmz0IdRqaBbgSlHt4zVhI6or4yGErYPHeFFwuNo5F2QKUJZLvAj+Ywf9gKEHGL R6Vj643K5ZTb4Xz/2fxI0erM+Bc/P+RLEo82rw7VIlpvjMuY8smdzLCvwb50ouu2 1k7IItgXtiWVjIkeEUjYq3m9C35ifyzt6gOPf1UaJx8p9OHP0Lm1yGnbK9ApKK2+ XBbprzfJbtDDOctKAwCbS1TA83wN30xVJr9r156ug9DgVoJauMXNA25vJ/Nycn9S EtVH6FD08zpzWoM6uOlA4dEhELC5vzVl9GbSPupdbMFmS7U0CBCcnfjCrZHaMemr 9CiibnBEK2YVJpYKI6E1AQsGVeNqUb68SoDZ5NQqQSSEXQB6w6i9Jho8bQ5I5UJc dQbIOcMN0tw5W3AFky2t =kU0Q -----END PGP SIGNATURE----- commit 8f96002526eb5e6b818d719ebe72a7db381eed39 Author: Robert Date: Sun Mar 9 09:06:51 2014 +0100 Added README ...
It prints tag author, creation date, message, GnuPG signature if present and the information about the referenced commit. If the tag is lightweight, the output will be limited to the information about the referenced commit.
Verifying signed tag
Additionally, if the tag is signed, the signature placed inside the tag can be verified to ensure that the tag was created by an authorized person:
$ git tag -v v1.4 object 8f96002526eb5e6b818d719ebe72a7db381eed39 type commit tag v1.4 tagger Robert <firstname.lastname@example.org> 1394358295 +0100 Release version 1.4 gpg: Signature made Sun Mar 9 10:44:55 2014 CET using RSA key ID A231EC80 gpg: Good signature from "Robert <email@example.com>"
In this case the tag was verified successfully so we can trust it. The verification may fail for two reasons. The typical reason is that we don’t have the signer’s public key. In this case we have to first obtain his/her public key and store it into our GnuPG keyring. Then we can retry the verification. The other unlikely reason is that the tag was created by an unauthorized person in which case we cannot trust this tag at all.
In most cases you would want to push the newly created tag to the remote repository to make it available to everyone in the development team. It can be done similarly to pushing the branches:
$ git push origin v1.4
Generally, there is no reason to delete the tags because they are inexpensive and don’t use much resources. The only exception is when you have mistakenly created a tag pointing to the wrong commit. In this case you should delete the local tag:
$ git tag -d v1.4
and remove it from remote repository if it was already pushed:
$ git push origin :v1.4
Moreover, if you have already pushed the wrong tag to the remote repository, the corrected tag should have different name than the wrong one. Otherwise, you may end up in a situation that some team members have a new tag while the rest still have the old one.
While I tried to describe the most interesting and useful functionalities related to tagging, there are still some things which were left out. You can find more about them in git-tag manual page.