Image of Git Tag | Git Tagging Explained

ADVERTISEMENT

Table of Contents

What is a Git Tag?

The Git version control system has many great features that help streamline the process of tracking files in coding projects. In this article, we will discuss the git tag command, which allows you to label your commits (and other Git objects) by assigning them readable names that can be easily referenced when traversing the history of a Git repository.

Git tags can be thought of as human-readable labels that can be used instead of the otherwise lengthy SHA-1 GUIDs that are used to reference objects in the Git database. A tag is technically a type of ref in Git, which is a label that points to a specific commit.

To show a comparison of how git tag can be used to make your commit history more reader friendly, let’s look at a basic git tag example:

$ git tag v1.0.0
$ git tag --list
v1.0.0

The first command above tagged the currently checked out commit as v1.0.0. The second command used the --list (or -l) flag to list the your Git tags.

To give you an idea of the convenience of git tagging, let’s compare the friendly name of v1.0.0 to the lengthy GUID associated with the same commit:

$ git log
commit 5972ad158f079fc9dd1991b4d1138fd2377816b4 (HEAD -> master, tag: v1.0.0)
Author: Initial Commit LLC <example@domain.com>
Date:   Fri Apr 22 15:39:43 2022 -0500

As you can see, it would be nearly impossible to remember the GUID while associating it with version 1.0.0 of our app. The version number itself if much cleaner, easier to reference, and easier to remember.

How Do I Use git tags?

Git makes using git tags flexible, and the naming of git tags is entirely user defined. That being said, when tagging commits in practice there is a commonly used naming convention called Semantic Versioning, which we’ll be using in our examples.

The Semantic Versioning convention defines versions like: vX.Y.Z:

  • X – The major version, used for making major and backward-incompatible changes.
  • Y – The minor version, used for adding functionality while maintaining backwards compatibility.
  • Z – The patch version, used for making small bug fixes while maintaining backwards compatibility.

Let’s take a look at an example Git project tree git-tag-ex/ with a few nested files and a nested directory dir1/:

git-tag-ex/
    file1.ext
    file2.ext

    dir1/
        dir1file1.ext

Next, we’ll add a few lines of comments to the previously empty file file1.ext:

file1.ext
// Sample text for our git tag tutorial.
// We’ll be updating the patch version using the semantic versioning convention.

Now let's add our changes to Git's staging area and commit them:

$ git add .
$ git commit -m "Added sample comments."
  [master 3ab27dd] Added sample comments.
  1 file changed, 2 insertions(+)

And finally, let’s tag this new commit with an updated patch version. Keep in mind, git tag will default to currently checked out commit, i.e. the commit specified by Git HEAD.

$ git tag v1.0.1
$ git tag -l
  v1.0.0
  v1.0.1

As you can see from the output, we have a new version v1.0.1 that represents our latest patch version update.

Create a Lightweight Tag With git tag

Git defaults to using what are called lightweight tags. Git stores each lightweight tag as a file in the .git/refs/tags directory. In fact, we can locate our previously created patch version tag in this location and take a look at the contents:

$ cat .git\refs\tags\v1.0.1
3ab27ddc62de25e030cfb734f54e59bd1850b280

We can see from the contents of this file that a Git lightweight tag is simply a file in the .git directory that contains the GUID of the tagged commit.

Create an Annotated Tag with git tag

Oftentimes, it’s wise to include some additional information when creating tags in Git.

Git annotated tags are stored as full objects in the Git database, and include useful metadata related to each individual tag.

Annotated tags allow you to include messages with each tag in similar fashion to commit messages, and also stores the tagger name, email and date the tag was created.

It’s also worth mentioning that annotated tags include security measures, and can be signed and verified with GNU Privacy Guard (GPG).

To create an annotated tag, simply use the -a option with our previously used Git tag syntax. Let’s commit a few more changes to file2.ext and try it out:

$ git tag -a v1.0.2
    hint: Waiting for your editor to close the file...

Using git tag -a without including a message inline will cause Git to open a file in your default editor that stores the annotated tag comment, and won’t complete the process of creating your tag until you save a comment and close the editor.

It’s easy to avoid this by creating a comment inline. We can commit a few more changes to file2.ext and see this in action:

$ git tag -a v1.0.3 -m "An example with an inline tag message"
$ git tag -n
  v1.0.0            Initial commit.
  v1.0.1          Added sample comments.
  v1.0.2          This is an example annotated tag.
  v1.0.3          An example with -m

As you can see, both methods stored our tag with the comment successfully. However, the latter method is a bit more convenient if you don’t need to document a lengthy message for your tag.

Listing Git Tags

Using git tag to list your tags is simple, and comes with a few options we’ll take a look at. A basic list of all git tags looks like this:

$ git tag -l
  v1.0.0
  v1.0.1
  v1.0.2
  v1.0.3

As we saw in the previous example, we can use git tag -n to view all tags and include the associated messages. If we have multiple tags with lengthy messages, we can limit the messages to a given number of lines with the following syntax: git tag -n[num] where [num] would be replaced with the number of lines in each tag message you'd like to display.

We can also supply git with a tag pattern to only return specified tags. For instance, if we had multiple major versions, and we only wanted to return version 1 tags, we could use the following example by specifying the pattern in quotes and using a wildcard *:

$git tag -l "v1*"
  v1.0
  v1.0.1
  v1.0.2
  v1.0.3

We can also sort our git tags in a lexicographic order by using the following syntax:

$ git tag -l --sort=refname <pattern>

Likewise, sorting by a tag's latest Git activity can be accomplished with the following syntax:

$ git tag --sort=committerdate -l <pattern>

And finally, we can list remote Git tags by using the following syntax:

$ git ls-remote --tags <remote>

As you can see, we have plenty of options for listing tags in Git.

Tagging Later Using git log and git tag

Throughout a project’s lifespan, the need may arise to go back through your commits and assign version tags appropriately. This can be accomplished using git log and git tag together. Let’s add a few commits to our repo, then go back through those commits and assign some tags.

First, we’ll need to run a git log and review some previous commits:

$ git log
commit c9a3186d7a592e76fc2d0743c484488f9db4c81f (HEAD -> master)
Author: Initial Commit LLC <example@domain.com>
Date:   Tue Apr 26 10:12:01 2022 -0500

    Example tagging later. Commit 3

commit 623f36f7ab68ccacf8a5c5e688b915abe47ed748
Author: Initial Commit LLC <example@domain.com>
Date:   Tue Apr 26 10:11:46 2022 -0500

    Example tagging later. Commit 2

commit d06902b982895fb1960280efaa06772ec2d1fd75
Author: Initial Commit LLC <example@domain.com>
Date:   Tue Apr 26 10:11:28 2022 -0500

    Example tagging later. Commit 1

commit 80e0ab4bd30aa89461d10cdc6bbef5645ae99f34 (tag: v1.0.3)
Author: Initial Commit LLC <example@domain.com>
Date:   Tue Apr 26 09:52:36 2022 -0500

    Using git tag with -m

commit 65339ed14c544f2bc4d8df4859bd8475515f10d6 (tag: v1.0.2)
Author: Initial Commit LLC <example@domain.com>
Date:   Tue Apr 26 09:50:23 2022 -0500

    More example comments.

commit 3ab27ddc62de25e030cfb734f54e59bd1850b280 (tag: v1.0.1)
Author: Initial Commit LLC <example@domain.com>
Date:   Tue Apr 26 09:31:51 2022 -0500

    Added sample comments.

commit 5972ad158f079fc9dd1991b4d1138fd2377816b4 (tag: v1.0)
Author: Initial Commit LLC <example@domain.com>
Date:   Fri Apr 22 15:39:43 2022 -0500

    Initial commit.

A quick review of our git log output tells us the our 3 latest commits don’t have tags. Let’s assume the commit with the message Example tagging later. Commit 1 is the one we’d like to tag with v1.0.4. The following syntax can accomplish this no problem:

$ git tag -a v1.0.4 d06902 -m "We can tag later with ease!"
$ git tag -n
  v1.0            Initial commit.
  v1.0.1          Added sample comments.
  v1.0.2          This is an example annotated tag.
  v1.0.3          An example with -m
  v1.0.4          We can tag later with ease!

Notice that we only need the first few digits of the commit’s GUID. Git is smart enough to deduce the commit we’re looking for, helping to simplify the process greatly.

As you can see from this example, traversing your commit history with git log and tagging commits later can be done with ease.

Pushing git tags to a Remote Repo

Once you’ve completed your tagging locally, you may want to push those tags to a remote repo. This can be done fairly easily with Git. If we wanted to push a single tag to our remote repo, we’d use the following syntax:

$ git push <tag-name>

Likewise, if you’d like to push all tags to your remote repo, utilize the following syntax:

$ git push --tags

Using the git push tag options makes keeping your remote repo’s tags up-to-date a fairly easy task.

Deleting Git Tags From Local and Remote Repos

Whether you simply incorrectly tagged a commit, or you realized later that you’d prefer a different tag for a specific commit, the need will arise to delete git tags. To remove a Git tag from your local repo, use the following syntax:

$ git tag -d v1.0.0
  Deleted tag 'v1.0.0' (was 5972ad1)
$ git tag -l
  v1.0.1
  v1.0.2
  v1.0.3
  v1.0.4

A glance at the output tells us our v1.0.0 tag was deleted successfully.

For deleting tags from a remote repo, utilize the following syntax:

$ git push --delete <tag-name>

It’s worth noting that Git has a separate tag namespace and branch namespace, and it's therefore possible to have a branch and tag with the same name.

To ensure you don’t accidentally delete the branch instead of the tag, you can specify the complete ref path to avoid deleting a branch:

$ git push origin :refs/tags/tagname

Summary

The git tag command is a tool used with the Git version control system to name your commits in a friendly and easy to read manner. It allows you to create tags, list tags, and delete tags from both local and remote repositories.

When creating tags in Git, it is common to use the Semantic Versioning naming convention. This allows you to keep track of your changes by breaking up version updates into major, minor, and patch updates.

There are two different types of git tags - lightweight and annotated. Lightweight tags are a simple reference to a specific commit. Annotated tags include other useful information such as the author name, the date, and the message.

Overall, git tag is yet another great feature included with Git out of the box. As you continue your journey utilizing the Git workflow, tagging is a must-use tool for any developer looking to create a well-organized project history.

Next Steps

If you're interested in learning more about how Git works under the hood, check out our Baby Git Guidebook for Developers, which dives into Git's code in an accessible way. We wrote it for curious developers to learn how Git works at the code level. To do this we documented the first version of Git's code and discuss it in detail.

We hope you enjoyed this post! Feel free to shoot me an email at jacob@initialcommit.io with any questions or comments.

References

  1. Git SCM - https://git-scm.com/
  2. Semantic Versioning - https://semver.org/

Final Notes