Flow Canon Work with us

Versioning Strategy

Using a software versioning strategy for your builds can reduce the cognitive load for everyone developing and using your software. Versioning Strategies allow you to identify each build artifact quickly and easily. What versioning strategy you use for your software is up to you and your team’s personal preferences. Here are some different options and some pros/cons for each.

Git Tags

When you’re using Git for your Version Control System (VCS), you already have a unique hash for every commit that you make. You can find the hash on the terminal with git log -1. If your Git repository is on production, you can easily tell exactly what is running by checking the git log.

Whenever you make a production release of your project, it’s best practice to identify the release with a Git Tag. This makes it easy to know what you shipped and when, and gives you some additional methods for rolling back to a previous version.

git tag v1.0.0 && git push --follow tags origin master

If you’re paying attention, in order to create a Git Tag, you’ve got to name it something.

Semantic Versioning: “SemVer”

MAJOR.MINOR.PATCH SemVer Documentation

Semantic Versioning is the most popular choice in open source and is widely adopted by the Ruby, Python, PHP, and Node.js ecosystems, with minor variations. Semantic Versioning is built using the glorious RFC2119. Each numerical version has its own meaning.

A MAJOR version must be incremented if there are any backward-incompatible breaking changes included in a release. This has the benefit of making it easy for anyone to quickly identify if a new version will work differently than a previous one.

The MINOR version must be incremented if there are backward-compatible functionality is introduced. In the strictest sense, this means you should be able to upgrade to a new minor version without experiencing any breaking changes.

The PATCH version is meant for backward-compatible bug fixes. You should expect no new functionality with a new patch version, only improvements.

Remember that each number in SemVer is treated independently. This means version 3.14.2 is more than 11 releases ahead of version 3.3.0. This will not be apparent as version 3.3.0 is higher in priority when sorted alphabetically.

SemVer also allows for pre-releases, but we do not recommend using them. Pre-releases A pre-release defy all logic of semantic versioning, meaning they ignore the conventions around breaking changes. Any pre-release may break at any time. If you’re considering releasing your software as 2.0.0-beta-1 through 2.0.0-beta-24, you might as well throw away SemVer all together and use Incrementing Build Number or Date Based Versioning systems, since there is no meaning in incrementing a beta number indefinitely.

Resetting the Version

Occasionally developers decide to reset their versioning for various reasons. MySQL released versions 5.5, 5.6, 5.7, and then jumped to version 8.0, leading some folks to refer to the previous 3 MINOR releases under MAJOR version 5 as 5, 6, and 7. Similarly, React made a change when they released version 0.14.8, followed by v15.0.1. SemVer’s recommendation is to start with version 0.x.x, which React did. In their case, the React Team decided their project was mature enough to skip version 1.0 all together as in their case the MINOR version had much more meaning than the MAJOR.

### Incrementing Build Number

Another somewhat popular methodology for versioning your software is to simply use the build number as set by your Continuous Integration System. This gives you a simple incrementing version to your Git Tags. You can still easily reference the Git Commit Hash and find the date of the release using Git.

Date Based Versioning

Date Based Versioning provides you with some information about when the release was made. Arch Linux uses Date Based Versioning in the following format: YYYY.MM.DD

If you are on a more frequent release cycle than once-a-day, you may have to also include time information to maintain a unique identifier for the artifact.

Hybrid System

Ubuntu is the most popular Linux distribution for web servers. Ubuntu follows a strict 6-month release cycle using a date-based schema. For example, 18.04, 18.10, 19.04, etc. Since Ubuntu is so critical to so many people, this release schedule makes sense for them. Like many mature projects, there is documentation for the Ubuntu Release Cycle, which allows everyone to plan ahead for changes.

Further, additional updates to each major version Ubuntu uses patch versions to indicate follow up releases to their major versions such as 18.04.3.

Software Versioning System Comparison

Versioning System Pros Cons
SemVer – Widely Adopted
– Generally Meaningful
standard-version npm package makes it easy to use
– Most open source ecosystems require usage for package distribution.
– Attempts to reduce the nature of changes to a number
– Specific conventions may vary from project to project and language to language, for example, Python PEP 440
– Pre-releases negate any worth
Incrementing – Simple
– Referrences CI Builds
– Does not convey any infromation about the nature of the changes
Date Based – Simple
– Very easy to identify when releases were made
– Does not convey any information about the nature of the changes
– Not ideal for releasing multiple times daily
Hybrid – Can use the best parts from SemVer, Incrementing, Date Based versioning systems
– You get to define for your own project how the system will work
– May not be consistent with any specific package manager’s requirements.
– Anyone developer using your software must understand your versioning conventions via your documentation

Additional Reference:

Choosing The Best Git Branching Strategy for Your Team

Choosing the best Git Branching Strategy for your team helps to deliver value to your production environment quickly and with a high degree of confidence. Generally, the best advice we can offer is to start simple. Don’t over-optimize your git branching strategy before you have something in your workflow that needs improvement.

Branching Strategies

If you find yourself as the only developer on a project, using a branching strategy that is less-than-the-simplest-tool-for-the-job is likely to be [premature optimization]. A single dev working on code should be able to get a single task into production within one business day from the time they start working on it. Yes, the code needs testing, so are including that time in our metric of “deliver value within one business day.” Tasks need to be small enough to be shipped in one day for this to be achievable.

The three primary strategies range from simple to complex in the following order: GitHub Flow, GitLab Flow, and Git Flow.

Start with the simplest thing that works.

GitHub Flow

GitHub Flow is a vastly simplified workflow compared to the process that Git Flow recommends. GitHub Flow is usually best for small teams that don’t need to manage several different environments or versions simultaneously.

GitHub Flow is trivially simple. You start from the master branch, checking out a new branch to do your work. When you’re ready for your work to be reviewed and merged, open a pull request to master.

Even if you’re a solo developer on a project, we still recommend you go through the process of opening a pull request, as it serves as a record of changes submitted. The work should be tested (on its feature branch), and when it is considered ready for deployment, the code is merged to master and deployed with due haste.

GitLab Flow

GitLab Flow is the newest popular branching strategy. It’s great for the case where you have multiple different environments that you need to support. In GitLab Flow, master is still your base branch, and the code is branched from master when you are working on features. Additional branches are release-purposed for different environments.

Example: Perhaps you have an iOS project, so you can’t control when your production releases are made (due to Apple’s review process). In this case, you’d cut a release branch at the time you want to deploy it, and employ some versioning strategy that makes sense for your team.

Work can continue regardless of changes from the appropriate release branch and cherry-pick those changes back into master. This workflow minimizes [drift] as much as you can, considering that you can’t control production releases.
It’s also useful if you need to deploy a series of changes to a staging environment. You’d cut the staging branch from master until the QA process is complete.

Advantages of GitLab Flow include the workflow still being simple. Master is your base branch, and [you shouldn’t merge untested code to your base branch]. If there’s a problem with a release, you can handle the changes in the appropriate branch, and promulgate those changes back to master.

Git Flow

Git Flow, the original article from 2010 proposed that master should be your production branch and that you should set the base branch to development to avoid confusion. While there’s nothing inherently terrible about this, due to the nature of changing the defaults, it does come along with some cognitive load for the team to consider at all times.

In our experience, Git Flow encourages [drift between environments], since development is by definition not equal to production. We’ve seen Git Flow abused such that broken code is merged to development and is allowed to make roost there for weeks before deployment.

Advantages to Git Flow are a highly rigid process. If your paranoia level is high for a good reason, Git Flow does provide some added protection. Compared with the other branching strategies, Git Flow increases the number of hoops that developers need to jump through in order to release code to production. If you have a rigid QA process and infrequent releases, Git Flow may be right for you.


Additional resources on Git Branching Strategies and when to use them