Going beyond semantic versions

How to read version numbers

Release version (x.y.z)

A normal released version uses the common semver format of x.y.z (eg: 1.2.13). Each value means major.minor.micro. x, y and z are always whole numbers.

This indicates that in the source repository there's a tagged version with exactly this and release documentation of the version.

And 'x' of 0 means this code is not in production anywhere.

Tagged version (x.y.zs)

A tagged version z is either a number and a suffix. Eg. 1.0.3a5

Suffixes starting with 'a' (alpha),'b' (beta) and 'rc' (release candicate) are version of a release older then x.y.z . eg: 1.3.4a3 is older then 1.3.4 and as well 2.4.3rc1 is also considered older then 2.4.3.
Suffixes starting with 'p' (post/patch) are sorted later then x.y.z.  Eg: 2.12.4p16 is considered newer then 2.12.4 (but older then 2.12.5) 

This indicates that in the source repository there's a tagged version with exactly this version, but documentation of the specific version maybe lacking.

Committed version (x.y.z+N.ghexhex)

A committed version is a version build from a version of the code that does not have an explicit tagged version. The version number will include a local part (after the '+') that indicates exactly which repository version was used. For example: 1.1.2+4.g27c7f7 is the 4th commit after tag 1.1.2. Any extra commit will change the 4 from 5 allowing for ordering of the commits. The g27c7f7 is the (g)it revision of the commit (27c7f7 in this case). This allows developers to find exactly what release it was.

Warning: N it's the number of commits it takes to walk back to the last tag. If you have multiple branches , it might very well be multiple versions with the same N. You can only use N for older-newer distinction while in the same branch.

Patched Version (x.y.z+N.ghexhex.hexhex)

This version was build from a source tree that was considered "dirty" (git diff reported changes). The last six hex digits are a hash of the change. This will make versions with different uncommitted changes have different version numbers. It does not allow to know which version is newer then the other. If the same patch is applied to difference versions, the last hexhex will be the same hash.

One interesting edge case is when there's a patch on a released or tagged version without it having any commits after the tag. These versions follow the same format. Here's an example of that case: 0.0.1+0.g000000.037c26

Note about Git tags:

Tags for versions much be annotated and signed repository tags. ($ git tag -a). You have to seperately push those tags to the shared repos

$ git tag -s tag # Create a signed and annotated tag in your git repo on the revision you've checked out.

$ git push origin # Push the existing tag tag_name.

https://www.python.org/dev/peps/pep-0440/#version-scheme Comparing versions:

To compare versions, you can use python's parse_version

>>> from pkg_resources import parse_version
>>> parse_version('0.0.1') < parse_version('0.0.2')
True  # Version number update
>>> parse_version('0.0.1') < parse_version('0.0.1+212.gd50833')
True  # Has commits after the version
>>> parse_version('0.0.1+212.gd50833') < parse_version('0.0.1+213.gd50833')
True  # Has more commits
>>> parse_version('0.0.1+212.gd50833') < parse_version('0.0.1+212.gd50833.92f55c')
True  # Tree was dirty when released.
>>> parse_version('0.0.1+212.gd50833.92f55c') == parse_version('0.0.1+212.gd50833.ab46f1')
False  # Two different dirty changes get a different versions