Why Versioning Is Important and How To Do It Properly
Implement Semantic Versioning so every dependency stays on the same page

You might be wondering what a number on software, a game, or an application means. Something like 11.2.3
or maybe 10.4.3.2arm64
.
These are the numbers of the version that the application is currently on or the version it belongs to. Furthermore, this is classified into different types for the same version.
Reasons for Versioning
But why should we version at all? Is it necessary?
Most likely, as the application grows, the number of dependencies included in the project will grow with it. The more dependencies, the harder it gets to manage things.
At times, you might find it difficult to upgrade a dependency without breaking contact with others that probably got too tight to upgrade.
Other times, dependencies are too loose. Some dependencies provide support for the future, more than is required at times. This is typically a dependency hell.
A simple solution to this is to start versioning properly, with a common set of rules, which helps every dependency stay on the same page as much as possible.
This is called Semantic Versioning.
Semantic Versioning
Semantic Versioning has certain rules that must be followed. These rules can be found on the website.
We consider a version format of X.Y.Z (Major.Minor.Patch).
- Bug fixes not affecting the API increment the patch version.
- Backward-compatible API additions or changes increment the minor version.
- Backward-incompatible API changes increment the major version.

You should read the rules so you know when to increment Major.Minor.Patch of the version and when not to.
But, isn’t it tedious to update the version of your project every time? There must be a several files where it needs to be updated and you need to remember when you did it last.
That doesn’t sound so interesting. What if I told you you can do it in a better way?
This where bump2version comes in. This GitHub resource is probably the best Python library for versioning I’ve found. How hard could it be?
pip install --upgrade bump2version
Once you are done with the installation, we need to create a bump configuration file so the script works the way we want it to.
Let’s assume we have a directory project_xyz
and there are two other directories in it: Backend
and Frontend
.
Let’s assume also, that Backend
contains a file setup.py
and Frontend
contains a file build.sh
. Each of these files contains the version of Frontend
and Backend
. These versions can be different or similar, depending on how you are incrementing (follow the rules).
We create a file .bumpversion.cfg
(note that it is hidden). This file is going to define where and to what the version should be updated.
We define the file as follows:
When you want to increment the version of the whole project you can run some commands in the root of project_xyz
and it will automatically update all the files.
As simple as:
bump2version major // 0.1.0 --> 1.0.0bump2version minor // 0.1.0 --> 0.2.0bump2version patch // 0.1.0 --> 0.1.1
Note that all the files mentioned contain a line:
version = 0.1.0 //or the version updated
But, whenever you want to do this for individual files (you’ve just updated the Backend
for example and want to increment only that), you might prefer:
bump2version minor Backend/setup.py
There is a way to increment with custom versions as well:
to go from 0.5.1 directly to 0.6.1:bump2version --current-version 0.5.1 --new-version 0.6.1 patch Backend/setup.py
Also, there is a way to add messages in versioning:
bump2version --message 'Build {$BUILD_NUMBER}: {new_version}' patch
When you make each commit to Git with all this information, that’s what I call one step closer to atomic Git usage.
I hope you enjoyed this article, thanks for reading!