Introduction
Let’s say your company is working on an open-source project where your team writes code, uses git to version the project, and creates multiple commits. There will be a point when your product is ready to be released for public use. When you release your product you will name the release with a version number and these version number follows the semantic versioning scheme.
In git, these version numberings are created with tags. Tags are nothing but a label for a particular commit in a branch. A real use case would be, you may work on bugfix/branch and after a couple of commits, you will be merging the bugfix with the main or release branch where you can create tags and release the next patch version for the product.
Real World Project
To make more sense of how the tag works with a real project, I picked the vagrant project hosted on github. You will see a section called tags in the repository. Click on tags and you will see a complete history of tags associated with this project.
Using semantic versioning scheme tags are created in the repository. Tags and releases are related to one another. Tags are git features and releases are github features where you will create release notes, and generate binaries through CI/CD pipeline like github actions, etc.
Create A Sample Project
If you wish to follow along, this section will help you in creating a sample repository.
Run the following commands which will create a directory called tags and create two commits.
$ mkdir tags; cd tags
$ git init .
# First commit
$ echo "First commit for tags" > ftag1.txt
$ git add ftag1.txt
$ git commit -m "TAGS - First commit for tag demo"
# second commit
$ echo "second commit for tags" > ftag2.txt
$ git add ftag2.txt
$ git commit -m "TAGS - second commit for tag demo"
To check the logs for your repository run the following command.
$ git log --oneline --all
206f49c (HEAD -> master) TAGS - second commit for tag demo
d065fdd TAGS - First commit for tag demo
Create Lightweight & Annotated Tags In Git
Git supports two types of tags lightweight and annotated tags.
LIGHTWEIGHT TAGS – This creates a pointer to a specific commit but does not store information like when and who created the tag.
ANNOTATED TAGS – This creates a pointer to a specific commit and stores information like when and who created the tag with the tag message.
To create a lightweight tag run the “git tag” command followed by the version number.
$ git tag <version-number>
$ git tag v1.0.0
To create annotated tag pass the “-a” flag. This will open the configured git editor for tag messages.
$ git tag -a v2.0.0
You can also pass the tag message with the git tag command using “-m” flag.
$ git tag -a v2.0.0 -m "second stable release"
If you run the git tag command it will tag the latest commit in the current branch. It is also possible to tag any previous commits. All you have to do is pass the commit hash to the git tag command.
$ git tag -a v2.0.0 -m "second stable release" 78b10ef
Move Existing Git Tag To Different Commit
If you want to move an existing tag to a different commit then use the “-f flag”. This will remove the tag from the existing commit and update with the given commit.
Without the -f flag you will get an error saying the tag already exists.
$ git tag v2.0.0 d065
fatal: tag 'v2.0.0' already exists
$ git tag -f v2.0.0 d065
Updated tag 'v2.0.0' (was 1df521f)
List Tags In Git
There are a couple of ways to check the list of tags in the git repository.
1. Git log command shows the tag associated with a particular commit.
$ git log --oneline --all
78b10ef (HEAD -> master, tag: v2.0.0) TAGS - third commit for tag demo
206f49c (tag: v1.0.0) TAGS - second commit for tag demo
d065fdd TAGS - First commit for tag demo
2. Running “git tag” without any argument will print the list of tags.
$ git tag
v1.0.0
v2.0.0
3. You can filter the list using pattern-based filtering. Use the -l flag and pass the pattern.
$ git tag -l "v2*"
v2.0.0
4. You can run the following command which will just print the names of lightweight and annotated tags.
# Lightweight tag
$ git for-each-ref refs/tags/ --format '%(objecttype) %(refname:short)' | awk '$1 == "commit" {print $2}' v1.0.0
# Annotated tag
$ git for-each-ref refs/tags/ --format '%(objecttype) %(refname:short)' | awk '$1 == "tag" {print $2}'
v2.0.0
Display Tag Information In Git
To get the metadata about a particular tag run the “git show” command. This will show tag-related metadata like the tagger name and email, tag creation date, and commit information along with diff.
If the tag is a lightweight tag you will not be seeing tagger and tag date information.
$ git show v2.0.0
tag v2.0.0
Tagger: nixzie <[email protected]>
Date: Sun Dec 11 18:07:56 2022 +0530
TAGS - second stable release
commit 78b10efa9a80e5a8f33ee20756054c78a1496cfd (HEAD -> master, tag: v2.0.0)
Author: nixzie <[email protected]>
Date: Sun Dec 11 17:57:21 2022 +0530
TAGS - third commit for tag demo
diff --git a/ftag3.txt b/ftag3.txt
new file mode 100644
index 0000000..05b5c68
--- /dev/null
+++ b/ftag3.txt
@@ -0,0 +1 @@
+third commit for tags
Push Tags To The Remote Repository
By default, tags will not be pushed when you push the repository to github, gitlab, bitbucket etc. You have to explicitly pass the –tags flag to push the tags.
$ git push -u --tags origin master
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 169 bytes | 169.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:nixzie/tags.git
* [new tag] v1.0.0 -> v1.0.0
* [new tag] v2.0.0 -> v2.0.0
Delete Git Tag In Local & Remote Repository
To delete any tag run the “git tag” command and use the -d flag.
$ git tag -d v2.0.0
Deleted tag 'v2.0.0' (was 06a8f0d)
To remove remote tags use the “–delete flag” with git push and mention the tag name.
$ git push --delete origin v2.0.0
To github.com:nixzie/tags.git
- [deleted] v2.0.0
Instead of the –delete flag you can use a colon followed by the tag name.
$ git push origin :v2.0.0
To github.com:nixzie/tags.git
- [deleted] v2.0.0
The problem with the above approach is when you have the same tag and branch name git doesn’t know which one to delete. In that case, you will get the following error.
$ git push origin :v2.0.0
error: dst refspec v2.0.0 matches more than one
error: failed to push some refs to 'github.com:nixzie/tags.git'
To fix this, you can use “refs/tags/tagname” which will delete only the tag.
$ git push --delete origin refs/tags/v2.0.0
$ git push origin :refs/tags/v2.0.0
Compare Two Tags With Git Diff
As you know git tags are just a reference to a commit. So you can compare two tags using the git diff command.
$ git diff v1.0.0 v2.0.0
diff --git a/ftag3.txt b/ftag3.txt
new file mode 100644
index 0000000..05b5c68
--- /dev/null
+++ b/ftag3.txt
@@ -0,0 +1 @@
+third commit for tags
Wrap-Up
In this article, we have seen what is tags and how to manage the lifecycle of git tags. If you have any feedback or tips, feel free to post in the comment section.