Introduction
To introduce Git Tags, we’ll need to revisit a concept that we software engineers all know inherently but don’t tend to think about that often. What does it really mean to develop a piece of software? Essentially, it comes down to adding changes on top of changes and (almost always) using Git along the way to manage them. So, today we’ll add a feature, tomorrow we’ll tweak another one, and the day after, we’ll fix a bug. This is the life of a software engineer.
Among all those changes we make every day, we’ll want to save some specific points. We may need to know exactly where we made a specific change; we may need to mark the start of a new version; maybe we just want to. We could always save the sha512 id of the commit and write it down on a piece of paper. But why go to that length if Git Tag can help us with that?
Git Tag? What’s That?
Git Tag is a functionality of Git that lets us snapshot our commits. In non-techie language, it’s basically the same as writing down the commit sha512 id and labeling it with a name we want.
So yeah, you guessed it: Git Tag lets us identify specific commits by naming them, thus making them more meaningful and user-friendly. It’s the difference between talking about “commit a54b72f” or “commit v1.3.2.” Which one sounds better to you?
On the other hand, Git Tags are in some ways similar to Git Branches. There are a few tricks you can perform with both of them; the main similarity is that both point to a specific commit, and the difference is that Git Tag is a static pointer while Branches are not. If you commit on top of a Git Tag, the tag will not move. But if you commit on top of a Branch, it will move to the latest commit.
Is There Any Reason Why I Should Use a Git Tag?
As I mentioned earlier, a Git Tag is a way of labeling a commit, and we might want to save some specific commits to know which ones they are. If you put these two points together, we can think of Git Tag as the ideal solution for, say, the version problem. Each team needs to version their software somehow. Using a Git Tag, we can label the commit we used to ship a new version to the production environment and call it “v whatever version we're into,” or whatever we want to call it. The pointer won’t move; therefore, when we start working on the next feature to release next week, we can work safely, because the Tag will always remain in the same commit.
Although Git Tags and Git Branches are very alike, they each have a distinct modus operandi. As previously mentioned, while branches move when we commit on top of them, Git Tags do not. If we use a Git Tag to mark a commit where we should start working, we might end up with our HEAD in detached mode, meaning that the commits we’ll perform from now on are not associated to any branch—and, if their sha512 id is not saved, their track could be lost.
Still on the subject of similarity, since branches and Tags are similar, we can check out to a tag just like we can to a branch. But again, the HEAD will be in detached mode, which can cause your commits to be lost.
Okay, Teach Me!
There are two types of Git Tags: annotated and lightweight. The lightweight tag is just a simple pointer to a commit. When viewed, it will show only the information of the commit. The annotated tag contains all lightweight tag information plus some information about the creator of the tag, the date the commit was tagged, and a tag message, if we choose to add one.
The simplest way to create a tag is by following this command:
git tag <tag name>
This command will create a lightweight tag in the commit we’re currently at—in other words, in our HEAD. If we want to create a tag in a specific commit, we just need to tell it to the command:
git tag <tag name> <commit sha512 id>
To create annotated tags, we’ll need to start using the tag command flags. In this case, do it like this:
git tag -a <tag name>
If you also want to add a tag message (remember, it’s optional), the flag -m will do the trick:
git tag -a -m “<tag message>”
Don’t bother trying to create a lightweight commit with a message. Git will refuse your command because the message is only for annotated commits; therefore, if you use -m, you need to use -a as well. So far, these all commands will only create tags locally. No colleagues will be able to see them if you don’t push it to the remote repository. This isn’t a default thing Git does, so you need to tell it to do it for you. To do that, you can use the push command with a minor tweak:
git push origin <tag name>
Or, if we don’t want to bother picking all tags one by one:
git push origin --tags
On the other hand, let’s say we want to delete a tag. We’d need to go back to our git tag command and use the -d flag:
git tag -d <tag name>
But again, this is only local. If we want to push this change so our colleagues can see it, we’d need to tweak the push command again. We’d do it like this:
git push origin --delete <tag-name>
You’re probably wondering how we could just delete every tag. Since there’s no straightforward way, I’ll leave this StackOverflow answer here to help you with that.
Now onto checking out. It’s a complete no-brainer. Remember the fact that tags are similar to branches? The command is the same as well:
git checkout <tag name>
Wrapping Up
I imagine Git Tags a lot like labeling our jam jars at home—like literally picking up a pen and a piece of paper, writing “Pumpkin Jam,” and then gluing it to the jar. You can think of them the same way if you want. At the end of the day, you’re labeling a nameless commit with a meaningful term so nobody will eat (start a branch off) the wrong one by mistake and end up with a big allergic reaction (very messed-up codebase for the new feature).
So, hopefully now you understand how to let your colleagues know that you shipped the commit e98b3217 as version 2.3.8 to production the other day—without actually telling them as much. You can just write them a note that says “Check Tags.” That’s what they’re for in the first place.
This post was written by Pedro Barbosa. Pedro has been working in the software engineering world since starting his career in August 2017. A front-end developer, so far he's mastered Angular 2+, JavaScript, and TypeScript, and he recently started working with React. And you should expect his list of competencies to keep growing in the coming years, as he also loves to learn.