Semantic Tagging with Git

Nico Hormazábal
3 min readDec 2, 2017

--

I like Semantic Versioning, helps you understand the evolution of the projects based on the release’s version. Is it major? Just a patch? Semantic versioning helps you understand in a very high level through a quick glance what’s behind a release.

So a while ago (about a year now), I was thinking about a way to keep track of my releases and automate as much as possible the process of versioning following Semantic Versioning and keep track of the releases. I mainly use Git as my VCS, so obviously I was using tags for linking releases to specific commits.

By then I was using Netflix’s Nebula plugins (more specifically the Nebula Release Plugin, which uses gradle-git), that are pretty handy specially if you are releasing to a Maven repository since it takes care of versioning, tagging, and do the release. But I was looking for something simpler, only for tagging and not attached to Gradle, but something that could be used on almost any environment.

So the idea of creating a bash scrript came to me. Plus, I had very little experience on Bash scripting (and I still do), so it was a great opportunity to learn.

Semtag

So I created Semtag. Semtag is a Bash script that depends on Git (so Git is mandatory here) and creates semantic versioning tags for you. Just specify the scope you want (major, minor or patch), and the script will bump the version for you, and push the tag.

$ ./semtag getcurrent
v0.0.5
$ # Do some changes and push them to remote
$ ./semtag final -s patch
* [new tag] v0.0.6 -> v0.0.6
v0.0.6

Semtag also supports automatic detection of the scope, which is something I personally don’t recommend, but there it is because I thought it was cool: Basically checks the percentage of lines of code that changed since the last version, and if the changes represent more than 10% of the total lines of code, it sets the scope as minor, if it is lower than 10%, then considers it as a patch (yeah, pretty arbitrary, and you could even change a single line that could represent a major change on your project, so use this option with care, or don’t use it at all).

Also it handles release cycle versioning, so you have to specify if your version belongs to an alpha, beta, release candidate or final version (beware, final versions can only be released from the master branch).

But wait, there is more: if you generate a version with uncommited or unstaged changes, the version will show the amount of commits since the last tag, and the hash of the current commit.

$ ./semtag getcurrent
v0.0.5
$ # Do some changes
$ ./semtag getcurrent
v0.0.6-dev.unstaged+b4c662d

One of the things I liked the most from the Nebula Release Plugin is that the tags contained comments with all the commits included in the release. Semtag does that too, and for each version tag, it includes all the commits from the last final tag.

Semtag includes with the tag message all the commits since the latest final version

We use Semtag in my team at work for automatic tagging the versions of our services on Travis, just after merging with master and before deploying. Also on our Android Libraries, semtag is used for keeping track of the versions, and our releases to our internal maven repository are using the version generated by semtag.

Check the readme at the repo for more details, and remember that most of what I know about Bash scripting is what I learned doing this script, so any suggestions or fixes are more than welcome.

Semtag: https://github.com/pnikosis/semtag

--

--