Tags are ref’s to specific points in a repository’s history, it’s like a snap shot of a Git reprepository’s. Is generally used to capture a point in history that is used for a marked version release with a version number identifier that correspond to software release cycles. A tag after being created, have no further history of commits.


Listing Tags

To list stored tags in a repo run the command git tag This will output a list of tags in alphabetical order:

$ git tag
v1.0
v2.0

To search in the list of tags the -l or --list option can be passed with an expression to match a particular pattern git tag -l "v1.0"

$ git tag -l "V1.0"
v1.0

Creating a tag

To create a new tag run the command:

$ git tag <tagname>

A common pattern is to use version numbers like git tag v1.4. Git supports two different types of tags, annotated and lightweight.

The differences between this two tags is in the amount of accompanying meta data they store. The lightweight tag is very much like a “bookmark”, it’s just a pointer to a specific commit, it’s useful for creating quick links to relevant commits, you can think of it as a private tag. In the other hand annotated tags, store a full objects in the Git database with extra meta data, they are checksummed, contain the tagger name, email, and date, have a tagging message and can be signed and verified with GNU Privacy Guard (GPG), this data is important for a public release for that reason you can think of it as a public tag. Suggested best practices for git tagging is to prefer annotated tags over lightweight so you can have all the associated valuable meta data.

Annotated Tags

$ git tag -a v1.0

Running this command will create a new annotated tag identified with v1.0. The command will then open up the configured default text editor to prompt for further meta data input.

$ git tag -a v1.0 -m "my version 1.4"

Running this command is similar to the previous invocation, however, in this version is passed the -m option and a message. This is a convenience method similar to git commit -m that will immediately create a new tag and forgo opening the local text editor in favor of saving the message passed in with the -m option.

Lightweight Tags

$ git tag v1.0-lw

Running this command creates a lightweight tag identified as v1.0-lw. lightweight tags are created with the absence of the -a, -s, or -m options. lightweight tags create a new tag checksum and store it.


Deleting Tags

Deleting tags is a straightforward operation. Passing the -d option and a tag identifier to git tag will delete the identified tag.

In the next example git tag is executed to show a list of tags, then git tag -d v1.0 is executed which deletes the v1.0 tag.

$ git tag
v1.0
v2.0
$ git tag -d v1.0
$ git tag
v2.0

Tagging Previous Commits

git tag will create a tag on the commit that HEAD is referencing by default. Alternatively git tag can be passed as a ref to a specific commit. This will tag the passed commit instead of defaulting to HEAD.

Runnign the command git log we will see a list of older commits

$ git log --pretty=oneline
26a2442f8cb0a468745b9e8295c046d9e13b9784 Merge branch 'feature_x'
e9ec67db76e012cbf4d63d05bc355e005d1a98b1 Add Feature X
7dc63c1d959dcc0673671d0c0e9c47fd24045664 Big Bang

In the next example we will pick the top most commit Merge branch ‘feature_x’ for the new tag. We will need to reference to the commit SHA hash

$ git tag -a v1.1 26a2442f8cb0a468745b9e8295c046d9e13b9784

Executing the above git tag invocation will create a new annotated commit identified as v1.1 for the commit we selected


Replacing Old Tags

If you try to create a tag with the same identifier as an existing tag, Git will throw an error like:

$ git tag -a v1.0
fatal: tag 'v1.0' already exists

Additionally if you try to tag an older commit with an existing tag identifier Git will throw the same error, if you need to update an existing tag the -f force option must be used.

$ git tag -a -f v1.0 26a2442f8cb0a468745b9e8295c046d9e13b9784

Executing the above command will map the 26a2442f8cb0a468745b9e8295c046d9e13b9784 commit to the v1.0 tag identifier. It will override any existing content for the v1.0 tag.


Sharing Tags to Remote

Sharing tags is similar to pushing branches but git push will not transfer tags to remote server by default, tags have to be explicitly passed to git push.

$ git push origin v1.0
Counting objects: 4, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 2.05 KiB | 0 bytes/s, done.
Total 4 (delta 3), reused 0 (delta 0)
To git@github.com:abellsmythe/test.git
* [new tag] v1.0 -> v1.0

To push multiple tags use the --tags option to git push command, like git push --tags. When another user clones or pulls a repo they will receive the new tags.


Checking Out Tags

If you want to view the status of a repo at a tag, you can do a git checkout of that tag, this puts your repository in “detached HEAD” state, which has some ill side effects. In *“detached HEAD*” state, this means any changes made will not update the tag, will stay the same, if you make changes and then create a commit that new commit won’t belong to any branch, will be a detached commit and only reachable by the exact commit SHA hash.

$ git checkout v1.0

If you need to make changes it is a best practice to create a new branch

$ git checkout -b version1 v1.0
Switched to a new branch 'version1'

When you make a commit, your version1 branch will be slightly different than your v1.0 tag