A simple scheme for software version numbers

There is as many opinions on how software version numbers should be structured than there is developers. It is difficult to design a scheme that is simple and that will stay consistent for the whole lifetime of a product – one good example of product that periodically change the meaning of the version number is the Linux kernel – at one time odd version numbers meant development code and even numbers production code. Now the rule seems that the major component of the version is incremented whenever the project leader feels that the minor component is too large.

My own schemes were always plagued by one annoying inconsistency: I always start the numbering at 0.1, meaning that the software is still in its design phase, postponing the switch to 1.0 to when the API (whatever this means) is stable enough that it can be guaranteed to not require corrections. The inconsistency becomes visible when trying to go through the next iteration of versions after 1.0, iteration that will be concluded by a version 2.0. Some people use very high numbers (1.99, and so on) for this purpose, but that never looked right to me.

So I finally found and adopted a simple scheme that (I think) clearly indicates which phase of the development process it belongs to. All version numbers follows the <major>.<minor&gt.<correction> scheme, starting at 0.1.0. A minor value of 0 always means that the API is stable (i.e. that this API will be maintained forever), and any other number that this is a different API and that this API is still under development (i.e. that users of this API should be prepared to modify their code). It will be simpler to understand with some examples:

  • 0.1.0: This is the first version, the API is still under development.
  • 0.1.1: Same API than before, but bugs in the implementations were fixed.
  • 0.2.0: API modified, but still not stable.
  • 1.0.0: First version using a stable API.
  • 1.0.1: Bugs fix on the stable version.
  • 1.1.0: A new development cycle started, with a different API.
  • 1.1.1: Same API than before, but bugs in the implementation were fixed.
  • 1.0.2: New bugs fixed in the stable API.
  • 1.2.0: New development version with a different API.
  • 2.0.0: Second version with a stable API.
  • 2.0.1: Bugs fix on the second stable version.
  • 1.0.2: New bugs fixed in the first stable API.
  • 2.1.0: Beginning of a new cycle of development, and so on…

One may ask why the numbering does not start with 0.0.0. In this case the minor part is 0 and that would mean that this is a stable API, but the only reasonable design for a stable API this early in the process would be the absence of API, which would require to release a first Debian package that contains nothing. So it seems reasonable to skip this step and start directly with version 0.1.0. But note how this is reminiscent of the way unit testing is supposed to be done, i.e. that tests should be written before the actual code that permit them to succeed is written.