All too often, I see people people pointing out flaws in Semantic Versioning (SemVer), or pointing out that it doesn’t apply to huge categories of software. (See quotes below).
- SemVer doesn’t apply to websites without a public API.
- SemVer doesn’t apply to stand-alone applications without a public API.
- SemVer doesn’t apply to internal development branches, only “releases”.
SemVer is … is also not perfect and
has problems, and while advocates of SemVer seem to think it is the
holy grail, there are reasons not to use, and many project in fact
don’t. An answer claiming that only SemVer exists misses a gigantic
part of the landscape out there. – Polygnome
you should in principle not use … semver …
Applying this versioning scheme to content …
it could be easier to fork it
to create your own versioning scheme, tailored to content …
“Why we’re switching [from semantic versioning] to calendar versioning”
( discussion )
Two version versioning schemes are in use. …
Semantic Versioning, or SV …
Date Versioning, or DV …
Older compilers, which only use SV, …
… — “Compiler Version Numbers and What They Mean”
Like an operating system, Twisted has a lot of parts, making SemVer a poor fit
… — Calendar Versioning (CalVer)
the state of “Semantic” Versioning, and why we should be fighting the good fight against it.
… — jashkenas
OK, so SemVer isn’t ideal for my project – how do I choose a different scheme which is more appropriate? Of course, this boils down to some kind of requirements analysis for my specific project. However, I suspect versioning isn’t something overly complex, so a few criteria or rules-of-thumb should be sufficient to make a decision. I hope one of the communities’ experts can contribute a short writeup or checklist how to approach this.
Or maybe there are well-defined versioning systems different from SemVer which allow me to choose from for at least some projects?
(I’d be happy to learn about such systems even if such a system is clearly worse than SemVer for other projects).
A version number is just a message, a way to relay specific information to a specific group of recipients. And just like any communication, the “best” message is the one that conveys the relevant information in the shortest and clearest way. What needs to be said, and who needs to hear it?
Who needs to hear it?
In order to know what information is relevant, you need to first define who it’s relevant to. There could be any number of recipients, all of whom might have a different standard for relevance:
- Developers might want versioning to help them discover when bugs were introduced. Knowing in what versions a bug appears, will help in finding the specific commit that introduced the faulty behavior.
- End users might rely on versions to decide their upgrade schedule. A major upgrade might require thorough testing, additional training, or even an upgrade to their paid subscription.
- Sales Associates might use the frequency of “major updates” to convince potential customers your application is the most actively developed, while the lack of minor versions is a clear indication that your software is practically free of bugs!
- Technical Support might have a list of the most-often reported bugs, and the versions where these bugs were first discovered and when they were fixed.
- Downstream developers who do not directly work on, but do use and rely on your library, will probably rely on versioning to tell them if their implementation/extension/add-on is going to break when they upgrade to a newer version. (This is probably the primary use case for SemVer.)
Ofcourse, these are just examples. You might need to deal with all, any, or none of the above.
What needs to be said?
Having figured out who your recipients are, you might have a general idea how much information you need to share. Perhaps you don’t need a defined versioning system at all. Or perhaps you’ll need multiple.
Some questions I can think of, that might be of help:
- How are upstream dependencies versioned? Mostly relevant to projects like add-ons, extensions, plugins, etc. But if your project has its own dependencies that all/mostly follow the same conventions, you might want to stick to those conventions, even if they’re not fully applicable to your situation.
- How are releases scheduled? Do you try to bundle major new features into one single ‘major’ release, or are they released as they’re finished? What kind of distinction, if any, is there between “major” features, “minor” features, bugfixes, etc?
- How many versions do you release (and where)? Does your app run as a cloud service? Is it a downloadable binary, and if so, do you support multiple OS’s / platforms? Your version might need to reflect the environment the app has been built for. Or, if your application is pushed to a package manager or dependency manager, you might not have a choice but to stick to whatever versioning is dictated.
- How often do you release? (Also: How consistently do you release?) Yearly? Nightly? Somewhere in between? Perhaps you want a schema that categorizes releases by date, or your releases are so infrequent that you’d rather opt for a simple incremental number. A more complex release schedule might require more complex versioning.
- How do you release? As in, what system is used for building, releasing, and deploying? Perhaps your ecosystem is already opinionated on which versioning schema to use. Or maybe you use Git, and just store the latest commit hash as your version identifier.
- How many people are involved in the project? The more people collaborate on a project, the more things can go wrong. A bigger team probably needs a stricter merge/release workflow, which in turn will probably lead into a more detailed versioning schema.
Opinions / Examples
- Project Developers don’t really need numbered versioning – just include the build number and/or partial commit hash at the end – that’s what’s relevant to them. The rest is just fluff.
- If your project is a framework, library, API – i.e. if your market is Downstream developers – then seriously consider SemVer.
- To most end users (even other developers), bigger numbers are better. 2.0 is always more impressive than 1.7, even if your versioning is completely arbitrary. Versioning can be a marketing trick, if nothing else.
- It’s alright to maintain multiple versioning systems, or even combine them, if you can handle the overhead. Extend SemVer or CalVer with a build number or commit hash. Give your releases fancy, somewhat memorable names. Increment your version numbers to use primes only.
Whatever you choose; manage expectations.
Just about any versioning schema will work, as long as people know what to expect. If you’re going for something that resembles
MAJOR.MINOR.PATCH, explain to your audience what constitutes a major. Or a minor. If you decide to ditch the patch and minor versions, make sure to have an other way to communicate critical security updates or backwards breaking changes to your users.
How good are you at predicting the future? Really good? Then why are you here and not out playing the stock market?
If, like me, you suck at predicting the future then two sensible paths lay before you. Either choose a really flexible versioning scheme or be willing to jump to a different versioning scheme when the need arises. If you’re willing to jump you can focus less on future proofing flexibility and focus on your needs of the moment.
The problem with being willing of course is staying willing. Which brings up the issue Jörg W Mittag & Robert Harvey were commenting on. That is, who is receiving this version information?
If it’s the marketing department we’ve found a threat to your ability to jump systems. The marketing department needs time to get people excited about the new thing. They don’t really care what the name of the new thing is but once they blow the marketing budget getting whatever you were supposed to call it into peoples heads they need that name to not change. That’s a problem for us here when the version is part of the name.
That’s why many use codenames during development. These can be decoupled from the version that becomes part of the name. That decoupling allows the name version to be unique but meaningless. This can be vital to prevent embarrassments like releasing “XYZ 2022” in mid 2023. Some break this out of their versioning scheme entirely and call it “edition”.
Another group that consumes versions is bug reporters. When you’re supporting fielded code it’s really nice to give bug reporters a way to make clear exactly what they found the bug in. Here we likely need to wean people off of whatever the marketing department called it. A build number is far more useful here.
Yet another group are those writing code against our software. Those who care about its API. These are the ones who care about breaking changes being distinguished from patches and bug fixes. These are the people who need your versioning system to make sense to package managers and dependency resolution tools.
So when picking a versioning scheme think seriously who is using it and whether you can make a one size fits all choice really fit.
Some questions people will want to be able to answer after looking at your scheme:
- What product is this?
See name, edition1, modifier2 and whatever else the marketing department slapped on it.
- What API is this?
See major & minor2,3
- What binary is this?
See build4, patch2,3, micro2, oh and SHA5. Even source control tags6.
- Is this thing stable?
See major = 03, modifier2 may hint, and you can flat out declare what your last stable release was.
Give them answers to these questions and your scheme may last a few versions before you have to change it.