50% off your 1st seat of GitKraken Pro — only $4/month!

Semantic Versioning and Git Tags

The MIT Sloan website, like a lot of websites and apps, uses Git for managing its codebase. Like any system, when it comes time to deploy to production, the code gets packaged up as an artifact to be released. That artifact is a set standardized version of code at a specific point in time.  

The longer you maintain a project, the release management gets messier and more complicated.  Release management can get messy if you and your team lack a standard, concise way to determine what a release means. If you don’t have a reliable way to determine what’s changed in your codebase between releases, when you’re looking at a past release down the road, you may not understand what was pushed in which release.

One approach that has been proven to help manage releases over time is semantic versioning. Used along with Git tags, semantic versioning allows you to easily indicate the degree of changes in your production code and understand those changes when looking at them in the future.  Let’s look at the basics of semantic versioning, Git tagging, and how to combine the two together to create semantic Git releases.

GitKraken’s beautiful commit graph will help you visualize your project’s repo in a way you can quickly understand, making it safe and easy to version releases and manage past versions.

Defining Semantic Versioning

At its core, semantic versioning is just a numbering schema. It’s an industry-standard software development practice used to indicate the degree of changes that have gone out since the previous production release. 

If you look at any piece of software you use today, the product’s development team is most likely tracking their changes using semantic versioning. For example, your operating system and web browser are both going to have a semantic version number. It is used by almost everyone because semantic versioning is a clear, concise way to indicate a level of changes. 

Examples of semantic version numbers in a web browser, macOS, GitKraken, and Git release notes.

There are three parts to a semantic version number:

  1. The major number
  2. The minor number
  3. The path number

When each one of these increments, it means a different degree of changes has gone into your codebase.

Let’s first look at the patch number. When you have a patch release, like going from version 1.0.1 to version 1.0.2, this indicates that there have been bug fixes or trivial updates. These are not major alterations to your application’s functionality.

A minor release, like going from version 1.0.2 to 1.1.0, indicates that there’s been a change to functionality. This can be a functionality change, adding completely new functionality, or removing existing functionality. 

A major release, like going from version 1.1.0 to version 2.0.0, indicates changes that might break backward compatibility or significantly alter functionality. This could be everything from removing deprecated code to introducing a complete re-architecture of your application. Major version numbers tell people that there have been major changes and some things may no longer work as they did on the old version, or that there are new steps that need to be followed to get the same functionality. 

An example of a major, minor, and patch number

A semantic version, once set, should be considered set in stone. Once released, that version of the code cannot be changed. Once you’ve marked a version of your codebase with a semantic version, you are not supposed to change which state of your code that version points to. If you’ve released version 1.3.0, a minor release, and you realize you missed something, you can’t just arbitrarily add it to your Git repository and then re-tag that commit. If you’ve released a version that needs to be updated, you will have to create a new release, complete with a new semantic version number.

In the worst-case scenario, if you release version 2.0.0 of your application and then realize you forgot to add a bunch of files to your repo, you would have to create a new major release, going immediately from version 2.0.0 to 3.0.0. That is not fun for anybody.

Using semantic versioning in your project means being responsible for double-checking your version number before you release your code. As soon as your code is released into a production environment, you have to assume that somebody is using the code, and you should not change the version number. This is especially true for publicly released code, such as npm packages. 

Adding Git Tags

Because semantic versions are set in stone, this makes them perfect for combining with Git tags. A Git tag is a way to add a marker to a Git commit to signify that it’s a meaningful commit in some way. 

There are two different types of Git tags.

First are lightweight tags. Lightweight tags are basically just named pointers to a commit. It’s a human-readable name that you can assign to a Git commit hash. To generate a lightweight tag in the Git CLI, you use the git tag command followed by the tag name, and then potentially the hash of the commit you want that tag applied to. If you only want the tag to reference the current commit, you can omit the commit hash.

An example of generating a lightweight tag on the command line.

In GitKraken, you can simply right-click on any commit from the central graph and click Create tag here to assign a Git tag.

The other types of Git tags are known as annotated tags. These are the recommended types of tags to use in your projects because, in addition to being human-readable names associated with a Git commit hash, they become full objects in the Git database. Without getting too deep into Git structure via database, a ‘full object’ means that the object can be checksummed

Annotated Git tags are also the recommended type of tags to use as they contain additional information about the commit, like who created the tag, when they created it, as well as providing tag messages in addition to the commit message. For public projects, they can be signed and verified using systems like PGP or GPG

Using the git tag command can be used to make a lightweight tag, but appending the -a flag will denote it as an annotated tag. Adding the -m flag will provide some sort of annotation message, and the hash for the commit you’re applying the tag to. 

Example of an annotated tag

In GitKraken, again like lightweight tags, all you need to do is right-click on a particular commit from the central graph and select the Create annotated tag here option.  GitKraken will guide you through the rest of the process.

Creating an annotated tag in GitKraken.

Whether you prefer the visual power offered by a GUI, or the control of the CLI, GitKraken has you covered.

Annotated Git Tags + Semantic Versioning

There is a lot of value in naming your annotated tags using the semantic version number.  This practice generates semantic releases, sometimes referred to ​​semantic version build numbers, which allow you to have marked commits in your Git repository with a specific version number. If you change the major, minor, or patch version number, you’re indicating the level of changes since your last Git tag. This is a very helpful way to demonstrate the level of changes in your codebase.

Using semantic releases in a Git repository allows you to more easily review your history and track how and when changes were made in your codebase. This is really helpful to you, but also to your team and potentially your users, especially when viewing your release notes.

The use of semantic versioning for your Git tags is supported by many product interfaces. For example, semantic versioning is supported by GitKraken for working locally, and GitHub for online repositories. Many systems make it easy to expose a release number or tag interface. These interfaces can quickly help you find which releases were patch updates and which ones included major functionality changes.

GitKraken and GitHub interfaces for exposing tags

Semantic Releases for Automation

Using ​​semantic version build numbers for naming your annotated tags also helps with automating your process. When using automation tools for your production deployments, such as CircleCI, you can indicate in your config.yaml that a job should only be executed on certain tags. If you use semantic versioning, you can put in a very simple regular expression to track that change and trigger actions only on tags matching the structure of a semantic version.  You can do this in other systems like Bitbucket Pipelines, Jenkins, or Travis CI as well. 

Watch a clip of GitKon speaker, Michael Miles walk through the process of creating a semantic release both through the terminal and using GitKraken to add an annotated tag and push the tag to a GitHub repo.

You will never lose track of a tag again with GitKraken’s powerful search and filter capabilities. Plus, you can create a new tag in just 2 clicks. 💯

Semantic Versioning and Release Notes

While semantic releases are extremely useful to the internal team working on a project, if you are going to expose these release numbers externally in your release notes, there are still a few additional considerations. There are multiple approaches to creating release notes—the accompanying documentation pushed out with most software releases—but in every case, the goal is to provide information beyond just: “the code was updated.”  If you just do the bare minimum of exposing the ​​semantic version build number in these release notes, this can provide a degree of changes, but it doesn’t provide any information about what changed. While you may be able to get away with this for patch releases, it’s not enough for minor or major updates.

Minor changes, or any change that introduces new functionality, needs, at a very minimum, to expose the annotation messages and provide usage details. Ideally, these details could be included in the annotation message. 

Major releases, or any release that requires people to do some sort of upgrade, should give people an understanding of any actions that they will need to take as a result.  

Guidelines for release note annotation usage in chart form

For completely private repositories and projects, detailed release notes might not be warranted. However, it’s still critical to keep the internal team informed of changes over time. At the very least, generating a list of the commit messages that have happened between releases can serve as the message for your annotated tags. This can save a lot of time tracking down when certain changes were introduced, even if you are visualizing your Git history with GitKraken.  

Making Your Life Better with Semantic Versioning and Git Tags

Watch a clip with some ‘extra credit’ advice on how to do even more with semantic versioning and Git Tags.

There are a lot of advantages to combining semantic versioning and Git tagging for your projects, both for your dev team and for your end users reading the release notes. Standardizing on a semantic release approach allows you to better automate your processes and exposes changes in a way that future developers will certainly appreciate. GitKraken can help make your life even better by making tagging a lot less painless, both in creating and viewing your tags.  Download the GitKraken Git client today, which includes a GUI and CLI, and get started down the path to semantic releases.   

Make Git Easier, Safer & more Powerful

With the #1 Git GUI + Git Enhanced CLI

Visual Studio Code is required to install GitLens.

Don’t have Visual Studio Code? Get it now.