How to manage the version number in Git?

GitVersion ControlVersioning

Git Problem Overview


Let's imagine the blerp command line tool maintained on [tag:Git]. This tool has the (hidden) --version option which returns its version (let's say 0.1.2) and another --commit which returns the commit number from which it was built.

Both the version and the commit number are hard-coded on the code base.

Now I make a bugfix then commit and rebuild my program. I will still see 0.1.2 although this new version differ from the original 0.1.2. Only the commit will tell me that it is not the same 0.1.2. Is that bugfix worth a different version number?

One solution is that each time I make a commit, I increase the hard-coded version number (which implies to always modify a minimum of 2 files for each commit). This is a binding solution and it does not work when the developers are working on different active branches. If Bob works on feature foo from the version 0.1.2 and Alice works on feature bar from the same version. How do they increase their version number? Bob can use the odd and Alice the even. What if Eve works on a third feature?

Another solution can be to use the Git tags to automatically generate the version number. A script can find the closest tag starting with v such as v0.1.2 and use the tag name as the version number plus the first n digits of the current commit (v0.1.2 (build 4acd21)). This works well if the working directory is clean. One can imagine to add a * before the build number to indicate the working directory is not clean. The main problem with this solution is if somebody export the sources, it won't be able to build blerp.

What possible alternative can solve this issue?

Git Solutions


Solution 1 - Git

Alexey Kiselev and Dario already hinted towards the answer, but I will try to explain it in detail.

Versioning Schemes

There are two types of versioning schemes:

  1. Internal version number: This can be incremented many times in a day (e.g. revision control number)
  2. Released version: This changes less often (e.g. semantic versioning)

People use different schemes as per their need, but semantic versioning is fairly widely used and authored by Tom Preston-Werner, co-founder of GitHub.

Semantic Versioning

Semantic versioning follows the pattern of X.Y.Z

Or more readable would be [major].[minor].[patch]-[build/beta/rc]

E.g. 1.2.0-beta

major or X can be incremented if there are major changes in software, like backward-incompatible API release.

minor or Y is incremented if backward compatible APIs are introduced.

patch or Z is incremented after a bug fix.

How do we achieve this using Git?

By using tags:

Tags in Git can be used to add a version number.

git tag -a "v1.5.0-beta" -m "version v1.5.0-beta"

adds a version tag of v1.5.0-beta to your current Git repository. Every new commit after this will auto-increment tag by appending commit number and commit hash. This can be viewed using the git describe command.

v1.5.0-beta-1-g0c4f33f here -1- is the commit number and 0c4f33f the abbreviation of commit's hash. The g prefix stands for "git".

Complete details can be viewed using:

git show v1.5.0-beta

Solution 2 - Git

Please, have a look at git describe command. This command shows you the latest tag and an amount of commits made after the tag was set. It also possible to show the dirtiness of the repository.

As you mentioned this command wouldn't work without the git repository (.git folder) and git installed. But it's almost unimaginable developer today without git but with all other tools installed.

Solution 3 - Git

Revision numbers should be maintained by you, not by git. As, opposed to SVN, you don't have a incremental revision number growing on each commit, there's no way out of the box to git to contextualize what your version is.

Solution 4 - Git

As you say, versioning issues are usually solved in git using branch and tags(like semantic versioning pattern).

The better way is to use git to track only changes in the codebase, ignoring (using .gitignore file) builds files and maintaining a clean repository.

Builds results (pre/compiled files, executables files, distribution files, zips, exe...) could depend of environments variables (platform, system arch, etc) and should be keep separate in a registry.

If the codebase very big and hard to maintain, maybe you should considerate to divide it in smaller components (or git submodule) to avoid cross-dependencies at development time.

Solution 5 - Git

  1. Create file in project dir (or where you want) build_number and put it value 1 in this file

  2. Go to git dir and create file called "pre-commit" in .git/hooks/ (without .sample)

  3. Put this code there

> #!/bin/sh > > currentbuildnumber=cat build_number let "currentbuildnumber++" > printf $currentbuildnumber > build_number currentbranch=git branch | > tr -cd "[:alpha:]" git log $currentbranch --pretty=format:"%h - %an, > %ar : %s, Build: $currentbuildnumber"

Working for me :) enjoy!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnowoxView Question on Stackoverflow
Solution 1 - GitaaryanView Answer on Stackoverflow
Solution 2 - GitAlexey KiselevView Answer on Stackoverflow
Solution 3 - GitevertonView Answer on Stackoverflow
Solution 4 - GitDarioView Answer on Stackoverflow
Solution 5 - Git0arkcodeView Answer on Stackoverflow