2 minute read

Collapsed versioning is a strategy often used in pre-release branches that narrows the number of new versions generated by the commits in a branch so that they progressively end up to a single version which is the cumulative account of a whole range of commits. If you have already used pre-release branches you are probably confident with this kind of versioning but you probably wonder what’s the algorithm behind.

For a better understanding you can refer to this example, whose graph is:

Take a look to commits c1-c8 into a pre-release branch named alpha. They all have a separate version number that an organization can use to test at various stages, release to the user audience for early access etc., but in the end they all converge into a single regular version 1.0.0 (at commit c9).

The upside of this is that you can release intermediate versions without losing expressiveness in version numbers and, on the other side, still having those intermediate versions coherent with what the regular release will be.

If versions were not compressed in this feature branch, they would have been: 0.1.1, 0.1.2, 0.2.0, N/A, 1.0.0, 1.0.1, 1.1.0, 2.0.0 (see this other example). The problem would be that commit c9 would have been versioned as 3.0.0 (or 2.0.0 if ignoring c9’s commit message) so regular releases issued by the main line would have jumped from 0.1.0 to 3.0.0, with quite a gap in between. Moreover, commits c1-c8 would not have been named like regular releases, so the user audience could’ve been mislead if using a unstable version.

But how are collapsed versions computed?

First off, the need a new concept to be introduced, and that is the prime version.

With that in hand, each commit is versioned with the greatest between the two version numbers computed as:

  • the prime version bumped with the single instance of most significant identifier bumped in all the commits between the prime version commit and the commit before the current one, eventually bumped with the pre-release identifier
  • the previous version bumped with the pre-release identifier

Let’s take commit c8 as an example.

The prime version bumped is 1.0.0-alpha.1 computed by starting from the prime version 0.1.0 and bumping the most significant identifier bumped from c1 up to c7, which is major. Please note that there are two commits bumping the major identifier (c5 and c8) but we only bump once. The alpha pre-release identifier is bumped (initialized) against 1.0.0 so the final outcome is 1.0.0-alpha.1.

The previous version (1.0.0-alpha.3) with the alpha.3 pre-release identifier bumped results in 1.0.0-alpha.4.

By the Semantic Versioning specification (the one used in this example) 1.0.0-alpha.1 < 1.0.0-alpha.4 so 1.0.0-alpha.4 is picked and becomes the new version for commit c8.