What Are Git Tags?
Git tags are pointers to certain commits. They are like bookmarks. You can use any kind of convention you want to create tags. But most development teams use version numbers like v1.0.1 or v.1.1-a1 to create tags.
Creating Tags
There are two types of tags in Git:
- Lightweight Tags
- Annotated Tags
Lightweight Tags
The lightweight tags are easy to create. You can simply use the following command line:
These tags are stored in the .git folder of your working repository.
Let’s create a few lightweight Git tags:
$git tag Release-20190401
In the first case, we created a tag with “v1.0.1”. In the second case, we created a tag with “Release-20190401”. The lightweight tags don’t return any value. Also, it’s important to point out that because these two tags were done back to back, they are pointing to the same commit.
Annotated Tags
Annotated tags let you store more information. You can use the “-a” option to create these tags:
Let’s try to create an annotated tag:
It will pop-up a text window for you to enter a comment that should look like this:
# Write a message for tag:
# v1.0.2
# Lines starting with ‘#’ will be ignored.
Enter a comment and save it. So, now your tag v1.0.2 is saved with a comment. Alternatively, you can directly enter the comment in the command line like this:
Finding Tags in Your Code
Now that we have created a few tags, let’s see what we have:
Release-20190401
v1.0.1
v1.0.2
v1.0.3
We can see all of our tags are displayed in alphabetic order. You can get more information about the tags by using the “-n<number>” where <number> stands for the number of lines of the comments.
Release-20190401 Updated README.md
v1.0.1 Updated README.md
v1.0.2 My version 1.0.2
v1.0.3 My version 1.0.3
Here you can notice a difference between lightweight and annotated tags. In this example, “Release-20190401” and “v1.0.1” are lightweight tags. The “v1.0.2” and “v1.0.3” are annotated tags. All of them are pointing to the same commit (commit 34671):
commit 106e0bb02a58ec3e818e9acdf3bb19a9247a0e84 (HEAD –> master, tag: v1.0.4)
Author: Zak H <zakh@example.com>
Date: Sat Apr 6 21:06:02 2019 -0700
Added Feature 2
commit 161c6e564e79624623ed767397a98105426d0ec4
Author: Zak H <zakh@example.com>
Date: Sat Apr 6 21:05:25 2019 -0700
Added Feature 1
commit 34671d824f9b9951e57f867998cb3c02a11c4805 (tag: v1.0.3, tag: v1.0.2,
tag: v1.0.1, tag: Release-20190401)
Author: Zak H <zakh@example.com>
Date: Sat Apr 6 20:24:53 2019 -0700
Updated README.md
commit afe9b0c7c9fbce3c3d585afe67358a5eec226e2c (origin/master)
Author: Zak H <zakh@example.com>
Date: Sat Apr 6 20:23:55 2019 -0700
Init
However, the lightweight tags are showing the comments from the commit itself which is “Updated README.md”, while the annotated tags are showing the individual comments that were added to them during the tag creation process.
Tip: If you want to find the commit number of a particular tag, you can use the “git show” command:
tag v1.0.3
Tagger: Zak H <zakh@example.com>
Date: Sat Apr 6 20:43:30 2019 -0700
My version 1.0.3
commit 34671d824f9b9951e57f867998cb3c02a11c4805 (tag: v1.0.3, tag: v1.0.2, tag:
v1.0.1, tag: Release-20190401)
Author: Zak H <zakh@example.com>
Date: Sat Apr 6 20:24:53 2019 -0700
Updated README.md
diff –git a/README.md b/README.md
index 9daeafb..180cf83 100644
— a/README.md
+++ b/README.md
@@ -1 +1 @@
-test
+test2
Tagging Older Commits
You can also go back and tag an older commit. Let’s look at the logs:
106e0bb (HEAD –> master, tag: v1.0.4) Added Feature 2
161c6e5 Added Feature 1
34671d8 (tag: v1.0.3, tag: v1.0.2, tag: v1.0.1, tag: Release-20190401) Updated README.md
afe9b0c (origin/master) Init
$
We notice that the commit 161c6e5 doesn’t have an associated tag. We can tag this commit like this:
It will pop-up the comment window. After we put in the comment, we can see that we have the commit tagged now:
Release-20190401 Updated README.md
Release-20190402 Added tag to an older commit
v1.0.1 Updated README.md
v1.0.2 My version 1.0.2
v1.0.3 My version 1.0.3
v1.0.4 Added Feature 2
Removing Tags
Suppose, you decide that you don’t want the “Release-“ tags as they are confusing. You can first find all the “Release-“ tags:
Release-20190401
Release-20190402
Now, you can remove them with the “-d” option:
Deleted tag ‘Release-20190401’ (was 34671d8)
$git tag -d Release-20190402
Deleted tag ‘Release-20190402’ (was 6ee37bc)
If we check the tags again, we should only see the tags that start with “v”:
v1.0.1 Updated README.md
v1.0.2 My version 1.0.2
v1.0.3 My version 1.0.3
v1.0.4 Added Feature 2
Overwriting Tags
Suppose, we have a situation where “v1.0.4” tag is poing to Feature 2:
d7b18a4 (HEAD –> master) Added Feature 3
106e0bb (tag: v1.0.4) Added Feature 2
161c6e5 Added Feature 1
34671d8 (tag: v1.0.3, tag: v1.0.2, tag: v1.0.1) Updated README.md
afe9b0c (origin/master) Init
But we want the tag “v1.0.4” to be pointing at Feature 3. If we try to retag it, we get this error:
fatal: tag ‘v1.0.4’ already exists
We can overcome this problem with the “-f” option:
Updated tag ‘v1.0.4’ (was 106e0bb)
If we check the log again, we see that the tag has moved to the commit we want:
d7b18a4 (HEAD –> master, tag: v1.0.4) Added Feature 3
106e0bb Added Feature 2
161c6e5 Added Feature 1
34671d8 (tag: v1.0.3, tag: v1.0.2, tag: v1.0.1) Updated README.md
afe9b0c (origin/master) Init
Alternatively, you can also delete a tag and re-add it to a new commit.
Sharing Tags with Other Users
When you push your code to your remote repository, Git tags don’t get pushed automatically. If you want to share your tags with other users, you have to exclusively push them.
The tags can be pushed like this:
Counting objects: 12, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (12/12), 902 bytes | 150.00 KiB/s, done.
Total 12 (delta 0), reused 0 (delta 0)
To /Users/zakh/_work/LearnGIT/git_tagging/remote/project_mayhem
* [new tag] v1.0.4 –> v1.0.4
Now, if other users clone the remote repository, they will only see the tag that was pushed (“v1.0.4” in this case).
Using Branches vs Tags
Branches are useful for new features or experimenting. Generally, you want to branch when there is future work that needs to be done and the work is disruptive to your current development. On the other hand, tags are more useful as snapshots. You should use them to remember particular things that you have already done.
In Conclusion
Git tag is an under-utilized feature that can provide a great way to keep track of releases and special features. If you set up good practices around tags, it can help you easily communicate with your development team and simplify your development processes.
Further Study:
- https://git-scm.com/book/en/v2/Git-Basics-Tagging
- https://softwareengineering.stackexchange.com/questions/165725/git-branching-and-tagging-best-practices
- https://www.atlassian.com/git/tutorials/inspecting-a-repository/git-tag
- https://en.wikipedia.org/wiki/Software_versioning
- https://www.techopedia.com/definition/25977/software-versioning