25

I am trying to plan a system which validates the compability of different components by comparing their semantic versioning number, especially the major release number (since it indicates API changes and backwards compability). I came across the following scenario where I could not find an exact answer:

Let's say the code is on version 2.3.5 and I add a new major API change, therefore updating the version to 3.0.0. However, a few days after releasing I find that this change does not suit the users' needs, and I revert this change so that everything that was compatible with the versions 2.x.x will be compatible again (note that I'm not doing a version control revert, but rather put the old version of the code back in a regular commit). Now I can't figure out if the new version should be 4.0.0 because I again did a major API change and the numbers should always be incremented, or, because it will be backwards compatible again, use 2.4.0.

I see advantages and problems with both solutions. Are there ground rules or best practices for such cases?

Josef
  • 387

3 Answers3

30

Why you SHOULD go for a new major version according to semver?

Semver is a recommendation and not a regulation: ultimately, it's up to you to decide, as suggested by Bart. However, if you want to comply with semver, you MUST go to the next major version. First:

  1. Once a versioned package has been released, the contents of that version MUST NOT be modified. Any modifications MUST be released as a new version.

Second, because semver only defines version increase:

  1. Major version X MUST be incremented if any backwards incompatible changes are introduced to the public API.

Why you SHOULD NOT go backwards in the version numbering

First of all, it is perfectly possible to create a maintenance release for a previous but sill maintained version. So if you have a branch 2.3.5, 2.4.0 and 3.0.0, you can very well create a bugfix 2.3.6, or a (backwards-compatible) feature version 2.5.0, as long as you do not create an overlap between the branches.

However your scenario is different: going back for your main version creates inconsistencies . Suppose for example that you would go to 2.4.0:

  1. The latest most advanced version would no longer be the largest number. This breaks a lot of assumptions about increasing version numbering. For example:
    What version would you see as the latest stable version in your wikipedia page? what would the customers of version 3.0.0 think of you and your reliability if they discover that they have a version after the latest stable version? what version would customer download if they are looking for the most advanced?
  2. New major evolution could create new numbering challenges to avoid conflicts:
    If after 2.4.0 you would introduce a new major version, you would have to INCREMENT your major version. So it would be back again to 3.0.0. Would you rather go for 3.1.0 (but perhaps your new version goes in a totally different direction ans is incompatible with the former version 3.0.0)? Or jump directly to version 4.0.0? In this case you would only have postponed the brutal version number increase.
  3. How would you document that the API of version 3.0.0 is deprecated?
    "API 3.0.0 is deprecated from version 2.4.0 onwards"? really?
  4. Chained reaction! An official release has consequences: your clients may also have versioned packages. After all, that's what semver is meant for. Your backward numbering might mess up their recommendation for their own versionning and automated dependency management tools.
    Example: "if you use our package 7.1 you need his component 3.0.0; if you use our package 7.2 you need his component 2.4.0" - really?

Conclusion

I recommend to stick strictly to semver. Semver was not designed for marketing purpose nor for affinity. It was designed to facilitate the management of many dependencies between many components. The (consistent) number jump is really a minor inconvenience, compared to the assumptions a backwards numbering could break.

Christophe
  • 81,699
16

Usually, for things like semantic versioning, it isn't relevant how you technically achieve something, but rather what the intent is of what you try to achieve.

If your intent with the rollback of version 3.0.0 is to offer the features introduced with version 3.0.0 also to users of the 2.x.y versions without forcing a major version update on them, then calling it version 2.4.0 would be correct.
The future of the 3.x.y versions is not relevant there. It does not matter if you will be maintaining the 3.x.y version along with the 2.x.y version or only maintain one of them and call the other obsolete.

If your intent was to make a new major version and the compatibility with the 2.x.y version is just a coincidence, then it would be correct to call the new version 4.0.0

1

If no-one is using your stuff then you can choose any number you like.

If you have released to the world though, no-one is going to install an 'old' version.

OK they might if they find a bug, or if they use some other old thing which isn't compatible with the new version etc but all these scenarios involved them experiencing problems and finding workarounds. Its not the happy path.

If you have released v3 with new features, you simply can't roll back gracefully. If it has bugs you have to move forward and fix em in v3.0.0.1 or something.

If it was the wrong direction and you are moving forward with a different feature set, then you have to release v4 if you want people to use it over v3 or know that it is 'the latest'

There's no way to tell people "hey v3 was just bad, ignore it and use v2"

Ewan
  • 83,178