git

Introduce checkpoints in your code - Learn how to use tagging in Git

ello

Ayush Poddar

Posted on August 15, 2023

Introduce checkpoints in your code - Learn how to use tagging in Git

Tags in Git can be likened to checkpoints of a game. You can tag points in a repository's history that are important to you. Typically, tags are used to mark release versions like v1.0.0, v2.0.0, etc.

Tags are associated with a specific commit in your repository. In other words, after you create a commit, you can tag that commit with any name of you liking - e.g., v1.0.0, v2.0.0, etc.

In this post, I am going to tell you about the two types of tags in Git and how to create them.

Types of tags

There are two types of tags in Git:

  1. Lightweight
  2. Annotated

Lightweight tags

These tags are simply pointers to a commit. You can think of them as "bookmarks" to a commit. They cannot store any metadata apart from the name of the tag itself. As a best practice, these tags are generally used for temporary bookmarking and private use.

The command to create a lightweight tag is:

git tag <tagname>
Enter fullscreen mode Exit fullscreen mode

where tagname can be anything that you want.

Annotated tags

Annotated tags are stored as independent objects in the Git database, with its own SHA1 hash, and metadata. They are capable of storing metadata such as author of the tag, email of the tagger, date of tagging and a message describing the tag. The command to create an annotated tag is:

git tag -a <tagname> -m <message>

# Example
git tag -a v1.0.0 -m "App is open to the public now"
Enter fullscreen mode Exit fullscreen mode

If you provide a message using the -m flag, then you don't even need to provide the -a flag. You can just do: git tag <tagname> -m <message>

Annotated tags are useful when you want to push the tag to the public domain. They are useful because they can hold metadata like tagger's name and date of tagging. This information can help, for example, when trying to track the root cause of a bug.

Can a tag only point to the latest commit?

No. You can also create a tag that points to a previous commit. Consider the following git log:

305e248 - Ayush Poddar, 10 weeks ago : refactor: split into two methods
6f7f4ab - Ayush Poddar, 10 weeks ago : modify the instance doubles ensuring green specs
fe59bb7 - Ayush Poddar, 10 weeks ago : add logic to show different color for hidden files/directories
4f1333f - Ayush Poddar, 10 weeks ago : add colors for hidden files/directories
1e1f10c - Ayush Poddar, 10 weeks ago : modify indentations
28c188b - Claudio Bley, 3 months ago : Merge pull request #594 from ayushpoddar/show-abs-path-xargs
44c370b - Ayush Poddar, 3 months ago : Revert "version bump"
Enter fullscreen mode Exit fullscreen mode

What if we want to create a tag that points to commit 1e1f10c (modify indentations)? You can simply add the commit hash (1e1f10c) at the end of the git tag command. So the command would look like this:

# Lightweight tag
git tag <tagname> 1e1f10c

# Annotated tag
git tag -a <tagname> -m <tag message> 1e1f10c
Enter fullscreen mode Exit fullscreen mode

Viewing details of a tag

To view details of a tag, you can use the git show command. The command is:

git show <tagname>
Enter fullscreen mode Exit fullscreen mode

The output differs slightly for lightweight and annotated tags. In case of lightweight tags, only the associated commit's information is displayed. The sample output is shown below.

commit 305e2486f4431fc7e0487423f90ed380852194b2
Author: Ayush Poddar <ayush.mail.id@gmail.com>
Date:   Wed Jun 7 18:00:34 2023 +0530

    refactor: split into two methods

diff --git a/lib/colorls/core.rb b/lib/colorls/core.rb
index b558968..f5f7707 100644
--- a/lib/colorls/core.rb
+++ b/lib/colorls/core.rb
@@ -416,20 +416,32 @@ module ColorLS

     def options(content)
       if content.directory?
-        key = content.name.downcase.to_sym
-        key = @folder_aliases[key] unless @folders.key? key
-        key = :folder if key.nil?
-        color = content.hidden? ? @colors[:hidden_dir] : @colors[:dir]
-        group = :folders
+        options_directory(content).values_at(:key, :color, :group)
       else
-        key = File.extname(content.name).delete_prefix('.').downcase.to_sym
-        key = @file_aliases[key] unless @files.key? key
-        color = file_color(content, key)
-        group = @files.key?(key) ? :recognized_files : :unrecognized_files
-        key = :file if key.nil?
+        options_file(content).values_at(:key, :color, :group)
       end
+    end
+
+    def options_directory(content)
+      key = content.name.downcase.to_sym
+      key = @folder_aliases[key] unless @folders.key?(key)
+      key = :folder if key.nil?
+
+      color = content.hidden? ? @colors[:hidden_dir] : @colors[:dir]
+
+      {key: key, color: color, group: :folders}
+    end
+
+    def options_file(content)
+      key = File.extname(content.name).delete_prefix('.').downcase.to_sym
+      key = @file_aliases[key] unless @files.key?(key)
+
+      color = file_color(content, key)
+      group = @files.key?(key) ? :recognized_files : :unrecognized_files
+
+      key = :file if key.nil?

-      [key, color, group]
+      {key: key, color: color, group: group}
     end

     def tree_contents(path)
Enter fullscreen mode Exit fullscreen mode

In case of annotated tags, additional metadata such as tagger name, tagging date, etc. are also displayed. A sample output is given below. Notice the metadata displayed above the commit information.

tag annotated-tag
Tagger: Ayush Poddar <ayush.mail.id@gmail.com>
Date:   Tue Aug 15 13:38:36 2023 +0530

This is the sample tag

commit 305e2486f4431fc7e0487423f90ed380852194b2
Author: Ayush Poddar <ayush.mail.id@gmail.com>
Date:   Wed Jun 7 18:00:34 2023 +0530

    refactor: split into two methods

diff --git a/lib/colorls/core.rb b/lib/colorls/core.rb
index b558968..f5f7707 100644
--- a/lib/colorls/core.rb
+++ b/lib/colorls/core.rb
@@ -416,20 +416,32 @@ module ColorLS

     def options(content)
       if content.directory?
-        key = content.name.downcase.to_sym
-        key = @folder_aliases[key] unless @folders.key? key
-        key = :folder if key.nil?
-        color = content.hidden? ? @colors[:hidden_dir] : @colors[:dir]
-        group = :folders
+        options_directory(content).values_at(:key, :color, :group)
       else
-        key = File.extname(content.name).delete_prefix('.').downcase.to_sym
-        key = @file_aliases[key] unless @files.key? key
-        color = file_color(content, key)
-        group = @files.key?(key) ? :recognized_files : :unrecognized_files
-        key = :file if key.nil?
+        options_file(content).values_at(:key, :color, :group)
       end
+    end
+
+    def options_directory(content)
+      key = content.name.downcase.to_sym
+      key = @folder_aliases[key] unless @folders.key?(key)
+      key = :folder if key.nil?
+
+      color = content.hidden? ? @colors[:hidden_dir] : @colors[:dir]
+
+      {key: key, color: color, group: :folders}
+    end
+
+    def options_file(content)
+      key = File.extname(content.name).delete_prefix('.').downcase.to_sym
+      key = @file_aliases[key] unless @files.key?(key)
+
+      color = file_color(content, key)
+      group = @files.key?(key) ? :recognized_files : :unrecognized_files
+
+      key = :file if key.nil?

-      [key, color, group]
+      {key: key, color: color, group: group}
     end

     def tree_contents(path)
Enter fullscreen mode Exit fullscreen mode

Listing tags

To list all tags in a repository, you can use the git tag command (without any arguments). You can also supply the --list (-l) flag which takes an optional argument.

Using git tag --list, as it is, will also list all the tags just like git tag would. The sample output of running git tag --list or git tag is shown below.

v1.0.0
v1.0.1
v1.0.2
v1.0.3
v1.0.4
v1.0.5
v1.0.7
v1.0.8
v1.0.9
v1.1.0
v1.1.1
v1.2.0
v1.3.0
v1.3.1
v1.3.2
v1.3.3
v1.4.0
v1.4.1
v1.4.2
v1.4.3
v1.4.4
v1.4.5
v1.4.6
Enter fullscreen mode Exit fullscreen mode

How to filter the tags by their name?

You can provide an argument to the --list flag to filter the tags. The argument needs to be the pattern that you want to filter by. The pattern can be the exact string to match or a shell wildcard. For example, if we want to view only those tags which start with "v1.0", we can do:

$ git tag --list 'v1.0.*'

# Output
v1.0.0
v1.0.1
v1.0.2
v1.0.3
v1.0.4
v1.0.5
v1.0.7
v1.0.8
v1.0.9
Enter fullscreen mode Exit fullscreen mode

How to filter for multiple patterns?

The --list flag can also take multiple arguments. In such a case, all tags which match any of the provided patterns will be listed. For example, if we want to list all tags which start with "v1.0", along with the tags which start with "v1.4" we can do:

$ git tag --list 'v1.0.*' 'v1.4.*'

# Output
v1.0.0
v1.0.1
v1.0.2
v1.0.3
v1.0.4
v1.0.5
v1.0.7
v1.0.8
v1.0.9
v1.4.0
v1.4.1
v1.4.2
v1.4.3
v1.4.4
v1.4.5
v1.4.6
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this post, you learned about Git tags and the different types of tags supported by it. You also learned:

  • how to create tags
  • view details of a specific tag
  • List all the tags and filter them by their name

References

💖 💪 🙅 🚩
ello
Ayush Poddar

Posted on August 15, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related