
Stop Abusing Semver - CyanMagnus
https://samver.org/
======
MAGZine
I'm not going to advocate for completely abandoning semver, and I do think
that people abuse it or try to use it in places where it might not have been
originally intended.

That said, personally, my most hated anti-pattern (outside of not properly
tagging broken interface versions), is people refusing to tag a 1.0. In
theory, this allows folks to continue breaking the interface without calling
it a broken interface. In practice, these packages are already widely deployed
and NOT tagging a major version completely invalidates the versioning
mechanism all together.

The versioning scheme cannot do its job unless if you use all three fields. So
release a damn 1.0.0 already! Your software will never be perfect. it's ok.

~~~
mumblemumble
I'm actually OK with people following semver, and also refusing to tag a 1.0,
as long as they also refrain from advertising the product as stable and
production-ready. You can't have your cake and eat it, too.

~~~
mfer
If you refuse to tag a 1.0.0 and follow semver it means any change could be a
breaking change. This has an impact on consumers of the software. As a
consumer, I quite often value stability.

~~~
levosmetalo
If stability is important to you, just don't use software tagged 0.x.y.

It's not like it's going to be more stable if the authors are forced to mark
it 1.0.0.

At least authors are honest that their goal at the moment of release is not
stability but their freedom to break it every release if they see a reason for
it.

~~~
mumblemumble
It's not really about whether the software is actually more stable, it's the
signaling the project gives by choosing to hold their version numbers in
semver's semantic no-man's-land where the version numbers aren't expected to
give a clear indication of the severity of the change.

In particular, what the signal says is, "We aren't yet ready to think about or
support the needs of someone who's trying to use this in production."

Which, if the project is also then pitching the software as production-ready,
is a terrible mixed message. Maintainers really should pick one story and
stick with it.

~~~
kerkeslager
> In particular, what the signal says is, "We aren't yet ready to think about
> or support the needs of someone who's trying to use this in production."

> Which, if the project is also then pitching the software as production-
> ready, is a terrible mixed message. Maintainers really should pick one story
> and stick with it.

Yes, that's true, but you've got to realize that these messages are often
coming from different teams. Versions are more likely to come from engineers,
whereas pitches are more likely to come from sales. As an engineer, version
numbers are one of the few tools I have for telling the truth when sales is
lying. Engineers generally don't want to promise stability that isn't fully-
formed, because if a valuable enough client starts using it, then we end up
supporting some horrible half-baked interface until they decide to upgrade.

In that context, when you see version numbers disagreeing with marketing,
don't point the finger at semantic versioning as "refusing to tag a 1.0.0
release". They're the ones telling you the truth. Point the finger at
marketing.

In a larger sense, the sooner you start viewing all marketing as untrustworthy
and basing your decisions on evidence instead, the happier you'll be. Version
numbers are a small signal. Actual trial periods and getting to use the
software should be the real deciding factor. And don't make the mistake of
turning a trial period into a commitment without actually evaluating whether
the software does what you want it to.

~~~
mumblemumble
It's kind of hard to rest things like a huge chunk of the world's computing
infrastructure basing itself on OpenSSL long before the product put out its
1.0 release on the usual "don't trust marketing" finger-tutting. Did OpenSSL
even _have_ a marketing team back in the early 2000s?

~~~
kerkeslager
Sure, hype isn't necessarily based on marketing. That's why there's the word
"often" in my previous post.

I think in the case of OpenSSL, there was a huge need for what OpenSSL was
doing which justified a lot of people taking a calculated risk to use it. I'll
concede in that case that the risk may have actually even been justified.

That same logic doesn't apply to blahblah.io's "revolutionary" 0.x.y packages
on npm or pip, or the bleeding-edge SaaS of the week.

------
rswail
There seems to be a confusion between versioning an _API_ , which is the
_contract_ between a service and its clients; and versioning an
_implementation_ of that API.

I version the API with semver. If I add a new optional field, that's a bump in
minor. If I add to a list of enumerated strings, that's a bump in minor.

But if I change my internal database schema, that's a change in my deployed
service without any change in the API.

I use date-based release IDs for the service, because it marks a point in time
of my development.

So release 2020-07-29 of MyService might support API versions 1.0, 1.1, 1.2
and 2.0. Clients using 1.2 are backward compatible with 1.0 and 1.1. Clients
using 2.0 are not.

2020-07-29 is useful to SREs running MyService. It's irrelevant to the clients
unless it changes that list of available semver'd API definitions.

~~~
dragonwriter
> I version the API with semver

SemVer is very particularly about versioning implementations of the API, not
just the API itself. Only SemVer major and SemVer minor are about the abstract
API, SemVer patch is about implementation changes that correct bugs in the
implementation of the API, and the optional build part of SemVer (if it
changes without any higher level change) is about implementation releases that
have no impact on the behavior specified in the API.

You can obviously use SemVer-ish versioning for APIs, but a major reason for
SemVer is for automated tooling that relies on product version numbers and
doesn't separately understand identifying APIs and their version numbers as
implemented in the products.

------
Vinnl
> If your users have the ability to actively choose what version of your
> software they're using, it works.

I don't think SemVer is about choosing which version to use; it's about being
able to plan the impact of upgrades. So the only requirement really is for
your users to be able to actively choose _when_ to upgrade.

Which does still mean that breaking your API should be avoided: all a major
version release does is communicating to your users that it is likely to be
more work than a non-major upgrade, not actually lessen the work.

See also [https://vincenttunru.com/semver-
explained](https://vincenttunru.com/semver-explained)

I also don't buy this:

> Semver throws a complexity wrench in what would otherwise be straight-
> forward automated releases.

SemVer is part of proper communication with your users. So is a proper
changelog that explains how a release will impact them. If you have a properly
updated changelog, defining the scope of the version upgrade is trivial; if
not, you have the task of updating the changelog as a wrench in your release
anyway.

~~~
jdmichal
I think you misinterpreted the part about automation. I think the argument is:
How does an automated build determine what version number to assign the build?
The answer is generally that a human has to be involved.

This follows from the preceding sentence, emphasis mine:

> Another small note, when dealing with automated CI/CD pipelines, _the
> developer must always specify the semver to the automation_.

~~~
Vinnl
Yeah, but I don't think it's a problem that a human is involved - someone has
to tell the user what will be in the release.

That needn't necessarily be at the time of the release, btw. If you have a
consistent process to update your changelog, then if you do have some
completely automated release system that just releases every x time, it can
simply look at the changelog to determine what version number to give it.

------
derefr
AFAIK, the core use-case for Semver is OS package management — specifically,
it’s the ability to auto-update installed system packages, knowing that a new
patchlevel version of a system library won’t break the OS from applications’
perspective.

Distro maintainers have always been doing something like Semver, with their
own “compatibility versions” distinct from the upstream’s versions. Semver is
basically just a push to get the upstream developers to do the distro
maintainers’ work for them, by versioning things the way the maintainers
would.

Note that this has little to do with language package ecosystems in the
constraint-resolution / bundling / locking of deps sense. Rubygems et al get
frozen at build time (and as such, don’t _need_ Semver — see how long Golang
got along without module versions.)

Semver is instead for version negotiation at _runtime_ (or “ops time”, if you
prefer): it’s for resolving _symbols_ using _dynamic library loading_ ; or for
resolving which version of a _daemon_ to install, to be compatible with a
given _client library’s wire protocol ABI level_.

And for those use-cases, Semver is pretty much essential. If you’re not doing
it for your package, someone else downstream of you still has to.

~~~
trickstra
We want the ability to automatically update our npm packages too. So that use-
case is not limited to OS packages. It applies to anything that gets
distributed by packages and you want to easily update or install it. Who would
want otherwise?

~~~
derefr
There’s a difference between these two senses of “automatic”, though.

An “automatic” update of a language-ecosystem build-time dependency package,
is still curated by your (not usually _fully_ -automatic) release-management
process, like any other codebase change. With full CI/CD automation, some bot
(e.g. [https://dependabot.com/](https://dependabot.com/)) notices that a dep
has updated, and “proposes” a PR that updates your project’s lockfile; your CI
buildbot then notices the new PR, and tries building that branch to see
whether it compiles and all the tests pass; and, if everything looks good, it
merges the PR into the main development branch. Even then, it’s now just
merged into the ‘develop’ branch, and is not necessarily going to be a part of
a cut release yet. A CD bot may put it into a QA environment from there;
divert a percentage of traffic to it (ala
[https://github.com/github/scientist);](https://github.com/github/scientist\);)
and then _maybe_ eventually make the call that it’s not hurting your metrics,
and so switch the traffic fully over to it. But more often, there are usually
_humans_ in charge of that final cut-over switch, whoget to make a final call,
before this kind of “automatic” update fully hits prod.

Whereas, with OS packages, there’s no CI/CD pipeline — the version number on
the package (coupled with your auto-update config) is the “last line of
defense” standing between the package and your production system. You can set
up a mirroring QA environment that gets updates first; but this is effectively
just “smoke testing” — you don’t really get to “run all the tests” for your
entire OS and application layer over again, in light of e.g. a new libc, to
“prove”—at least in some minimal sense—that things will be fine in prod. You
just deploy the configuration, and observe that it’s “working.” _Maybe_ you
will have metrics on OS log volume or something similar; but OS package
updates often introduce new spurious logs that you don’t care about, so this
is a bad metric to track.

(Of course, you can do the QA traffic-splitting thing for your OS-package
updates as well... but this means slowing the cadence of OS updates / bundling
updates together so that you can gather enough data to say something about
whether each new update-bundle is “working.” And if you bundle enough updates
together, you’re effectively taking the reins of the OS from its maintainers,
with the OS becoming just another _part of_ your release-management process,
i.e. with you effectively cutting whole-VM-image “releases.” Which somewhat
removes the key advantage of automatic updates — especially automatic
_security_ updates, and _especially_ especially automatic _kernel_ security
updates [ala [https://ubuntu.com/livepatch](https://ubuntu.com/livepatch)].
You make yourself vulnerable to these discovered attacks in the interrim, in
the name of stability.)

When you think about it, as long as you’re operating in “full paranoia” mode
in both cases (as described above), then for the “build-time dependency”
packages, all the stuff the CI/CD pipeline does kind of _obviates_ versioning.
An incompatible new version of a dep that breaks your software, will just be
caught during the regular CI process. You may as well use the sort of
timestamp+gitsha versioning that the OP proposes; nothing would really change.
It’s only in the OS package case, where semver is getting you a benefit _you
wouldn’t otherwise get_ just from good release hygiene.

------
kristopolous
Microsoft did this right with a day counter and build number.

I often use git describe + tags + $(wc -l release history) + date + version as
I thought appropriate. Then I expose these strings at key places. x.y.z is
fine, do that, but we also don't need to be so precious with our bytes now. A
30 byte version string is totally fine.

From my perspective, things should be as nearly replicable as possible for bug
tracking and fixing. The current version (as in what explicit almost
reproducible build) some random person is using should be easily discoverable

When things break, I document it using these numbers. When things are added, I
document it using these numbers.

When tests fix defects, that as well.

Defects should have a story. When they came in, when they went out, what was
affected, etc.

I view them more as narrative checksums bringing sanity to the moving
goalposts of any project.

A competent person should be able to glance at it, see things in order,
consistent, and well described and not be confused.

That's the real purpose of this stuff. Anything less is failing.

The marketing number is just that. It's why slackware skipped a bunch. For
that, Ubuntus YY.MM system is the clearest one I've seen. 14.04 tells you
exactly when it was released, dates are kinda magical like that.

~~~
TeMPOraL
> _A 30 byte version string is totally fine._

As long as it maintains total ordering. The primary job of a version number is
so that you can compare two of them to tell whether one version is behind or
ahead the other one (and, preferably, by roughly how much).

I've seen people using VCS commit hashes as version numbers, which defeats the
purpose of having such a number.

~~~
eminence32
But if you have access to the code repository, the VCS commit hashes do allow
for total ordering. It's just that the ordering is only available to those
with access to the repo

~~~
account42
Most VCS are a tree, which implies a partial ordering, not necessarily a total
one. Unless you meant to order by the commit date, in which case you could
just include that in the version.

~~~
eminence32
Good point, that is true

------
vemv
The introductory paragraphs and the proposed Alternative are completely
disjointed.

The stated problems are caused by breaking API changes. The author says it
clearly: _don 't break your API_.

Now, how does a different version naming convention change anything? You still
have breaking changes, just with a different name. And I'm not sure at all
that dates make it any easier to spot breaking changes.

There's this very illustrative talk explaining why breaking API changes are
such a bad thing. [https://github.com/matthiasn/talk-
transcripts/blob/master/Hi...](https://github.com/matthiasn/talk-
transcripts/blob/master/Hickey_Rich/Spec_ulation.md)

~~~
betenoire
nah the author addresses this:

> Make a new thing, name it something else, figure out the migration that
> makes sense for you and your users.

If you follow that advice, you don't have a broken API and the rest still
follows.

~~~
vemv
It's also possible to follow the alternative and still keep breaking APIs.

It's much more effective to focus on a single thing (breaking change
rejection) than to pretend that one thing can be magically accomplished
through another.

~~~
betenoire
yeah, the scheme doesn't somehow prevent you from breaking your API. that's
still on us :)

------
s3cur3
For another perspective on “semver is a lie,” see the “Live at Head” talk from
Titus Winters of the Google core C++ team.

[https://m.youtube.com/watch?v=tISy7EJQPzI](https://m.youtube.com/watch?v=tISy7EJQPzI)

TL;DW: By Hyrum’s law, at sufficient scale, there’s no such thing as a non-
breaking change (including changing comments). Embrace that, and test
sufficiently that you can always take the latest dependency but detect when it
breaks.

~~~
Wowfunhappy
> (including changing comments).

Huh? I didn't watch, but practically speaking, how do you break something by
editing comments? Let's assume it's an actual comment and not a shebang line
or something.

~~~
marvy
I didn't watch it either, but...

Does your language have exceptions? Do the exceptions support stack traces? Do
those stack traces have line numbers? Well then...

    
    
        // old code: version 1.2.3
        if(problem1) throw new Exception();
        if(problem2) throw new Exception();
    

Meanwhile, we have client code that catches the exception and then inspects
the line number to see whether it was caused by problem1 or by problem2.

(You may say that this is crazy and no one would do such a thing. Maybe so.
But this at least proves that it's theoretically possible. Also, you'd be
surprised at what some people will do.)

Anyway, we upgrade to the new code:

    
    
        // new code: version 1.2.4
        // Helpful comment here; no other changes.
        if(problem1) throw new Exception();
        if(problem2) throw new Exception();
    

And of course this comment messes up all the line numbers, at which point we
can have anything from misleading error messages to system meltdown, depending
on what the client code used the line number for.

~~~
SahAssar
That's only if you consider line numbers as part of the public API, which
would be crazy.

~~~
marvy
I'm guessing no one is crazy enough to consider line numbers part of the
public API. And yet... I could imagine myself writing code like this if I were
desperate enough, even though I would know perfectly well that my code would
probably break the never next time I upgrade.

~~~
SahAssar
Sure, but that's because you know you've used a non-public API in which case
semver has nothing to do with the conversation.

~~~
marvy
good point

------
keithnz
I'll abuse it all I like. At the end of the day it's a format standard for
versions, whether you use it semantically or not. It has a well designed
mechanism for comparing versions. It allows adding of meta data to the
version, so you can build what commit, and what build run on your CI system
built it, or any other things you want. Many tools understand it.

I really struggle to see any meaningful downside in using semver, even if you
don't do it semantically, if all you really need is some ever increasing
number that is trackable through your system, it does that job as well.

~~~
q3k
> I really struggle to see any meaningful downside in using semver, even if
> you don't do it semantically,

It erodes the social contract of semver.

Without a common understanding and trust of semver you lose the ability to
have an educated guess on whether 2.4.3->2.5.0 is an API-breaking change.
Naturally, you cannot truly rely on this anyway (and dependency versions
updates need to be tested), but being able to have a general idea about your
dependencies' API breakage at a glance is a great help.

This becomes even more important in the case of transitive depdencies:
something that might be drive-by bumped by your direct dependency (satisfied
by the fact that it's only a minor release bump and _their_ use doesn't break)
might actually cause your direct use of that transitive dependency to break.

~~~
joppy
What is the social contract of semver, as a library consumer? If either the
patch or minor versions change, I should not care since everything is
backwards compatible. But if the major version changes, all bets are off. This
seems like almost no contract at all.

It seems to me that this same information could be communicated by combining
the minor and patch versions into one number, and changing the name of the
library rather than changing the major version number.

~~~
sixstringtheory
I like having the patch number set apart. I frequently run into bugs with
dependencies where the first thing I check is if they've released a patch, so
I can try that to fix the bug before digging any deeper.

Muddle that with minor revisions and that information is lost. Minor
revisions, in addition to signaling new functionality, also signal the
possibility of the introduction of new bugs.

~~~
joppy
So both patch versions and minor versions signal the possibility of
introduction of new bugs - is there a point to separating them?

------
albertzeyer
I like the date-based version. But you can also use a combination of both. But
a semantic version number in front, and the date behind. I use that for a
couple of projects, e.g.:

[https://pypi.org/project/better_exchook/](https://pypi.org/project/better_exchook/)

Current version: 1.20200318.213331. The date/time is taken from the latest Git
commit. Via this code:

[https://github.com/albertz/py_better_exchook/blob/2c106820ea...](https://github.com/albertz/py_better_exchook/blob/2c106820ea334027ce585daa78cdfda753b918cc/setup.py#L96)

If I need to break the API, or want to change the versioning scheme, I can
just increase the major version number.

For logging purpose, I also append the Git hash, and maybe "dirty", like this:

[https://github.com/rwth-i6/returnn/blob/7fa1f3e0595247c035b2...](https://github.com/rwth-i6/returnn/blob/7fa1f3e0595247c035b2641de9952f9227669475/Util.py#L292)

~~~
mfer
Are you familiar with [https://calver.org/](https://calver.org/)

------
Amorymeltzer
I think the important line a lot of folks here are missing when discussing the
"alternative" is this:

>Are you releasing software to other developers who are making concious
choices on when and how to depend on your software, as part of a dependency
tool (like ruby gems) across an organizational boundary? Then maybe use
semver.

And earlier:

>Do your users even care what version of your software they're using? Or do
they just want it to work?

Clearly semver has useful information imbedded into it, which a date+shortsha
doesn't, but the big take away from Sam is that there's a good chance your
version number doesn't matter to your users. Marco Arment (ATP, Overcast)
spoke about this on Under The Radar[1] but, as an example, semver for an iOS
app is meaningless for the typical iPhone user.

I personally use a date+sha versionish on a project because there's only one
way to use the software. The date tells users when anything got added or
broken, and is useful for communicating updates; the sha is mostly for me.

1: [https://www.relay.fm/radar/164](https://www.relay.fm/radar/164)

------
mfer
> Who's date? The date the customer sees it or the date the developer wrote
> it? Hopefully you have a continuous deployment pipeline in place, in which
> the customer gets an evergreen version without thinking about it, in which
> case our versioning should be developer centric.

This might work for a web page but an app... an app in any kind of environment
that tries to control for security (like some large corps)... likely not.

And, for server side software.... yeah, not going to do that.

This whole thing doesn't work well for shipped software.

If you don't like semver for shipped software... there's always something like
[https://calver.org/](https://calver.org/).

------
yjftsjthsd-h
That feels a lot like giving up. You have a date and a hash, which tells you
almost nothing. Yeah, semver isn't practiced perfectly, but it at least tries
to give you useful information.

~~~
lillesvin
Honest question: How do you feel e.g. "1.2.1 => 1.6.2" is more useful than for
instance incorporating dates, like: "2020.05.04 => 2020.06.20"?

From my perspective both schemes provide useful information but for different
purposes.

~~~
usrusr
Strict semver all too often ends up "47.0.0 => 53.0.0" because in the spirit
of xkcd 1172 "every change breaks someone's workflow" almost everything can be
seen as an API change. 47=>53 could be a quick succession of tiny but
technically breaking fixes in some backwater part of the API that hardly
anyone uses or it could include a once-in-a-decade major API redesign or two.

~~~
yjftsjthsd-h
I honestly feel like that's a symptom of a poor API design in the first place,
although I'm willing to agree that there can be a little wiggle room in the
"is it a breaking change if someone depends on a bug?" middle. If you have to
bump your major that often, at best maybe consider why, and at _worst_ at
least you're still making it clear to the downstream users that that's what's
happening! Better to explicitly mark "yeah, we broke API compatibility again"
rather than "we incremented the version integer again; good luck finding out
why unless you read the complete changelog".

~~~
usrusr
A lot depends on typed on typedness. If breaking changes are identified during
compilation then the cost of minor breakage somewhere is low. The quantity of
change is far more interesting than strict absence/presence. And it takes so
little change to get unexpected client code broken that I'm very sceptical of
attempts to prevent it in API design.

Take classic java for example. If you have a public interface adding a method
can break someone's client code because nothing can keep them from
implementing that interface and the implementing class might already have a
method with a colliding interface. If you went completely over the top with
compatibility expectations you could even argue that it's impossible (pre-
modules I think?) to add any class or interface at all because someone at
foo.com might have rudely put a client code class with the same name in your
precious org.bar namespace. Nothing in the language prevents that.

Trying to design out the possibility of breakage isn't worth it, you'll end up
with conventions that soften the definition of "breaking change" anyways (or
with the antipattern of major-only increments)

------
geofft
> _There is a way to programatically compare an interface and bump a semver
> string automatically, but down that path lies Swagger diffing_

No, you cannot do this.

If the _semantics_ of an API have changed in a backwards-incompatible way,
even if the _structure_ (name, parameters, types) did not, then you must do a
semver major bump.

If you somehow are disciplined enough to never change semantics
incompatibility for a defined API and you make a new endpoint, then you don't
really need semver at the product level. You need a way of conveying what APIs
exist, but a mechanical version like 1.200.0 would work for that, or just
client discovery.

> _Without outside information, when trying to communicate a feature or a
> bugfix, whats easier, "/foo was added in version 27" or "/foo was added in
> 2008.02.28" ?_

Using the date does not work if you release version 26.1 on March 1st.

CalVer is great for the limited use cases where you never maintain stable
branches and all your clients can use the latest version - but at that point,
ideally you don't need versions at all, just use HEAD. If your clients cannot
reliably and automatically use the latest HEAD, then that's a sign that stable
branches are a problem you will soon have to think about.

CalVer where you pick some date of branching and add a point release (e.g.,
"Ubuntu 18.04.2 LTS," released well after April 2018 but part of a stable
branch cut in April 2018) also works well, but cannot be automated in the
fashion the author advocates, and certainly cannot answer "When was this
feature added," because the feature could have been backported to the stable
branch.

------
tmcw
Generally agree with this: semver makes a lot of sense for code libraries,
makes almost no sense for anything else. CSS, styles, and user-facing
documents have no concept of compatibility without change, because they have
no real implementation-hiding: they should probably just be incrementing
integers.

------
moron4hire
I've found a lot of complaints about SemVer can be fixed by tacking a
vestigial "1." on the front of the version. You keep everything else the same,
and that front "version" number is for "complete overhaul".

~~~
erik_seaberg
RPM let you bump "Epoch" from 1 to 2 when you needed to default on your entire
"Version" scheme and start over, though it can be confusing because it's sort
of hidden.

~~~
teddyh
Debian (.deb) package versions also have epoch:

[https://www.debian.org/doc/debian-policy/ch-
controlfields.ht...](https://www.debian.org/doc/debian-policy/ch-
controlfields.html#version)

------
debaserab2
Using dates as release version names has its own problems. The key thing I
find challenging with them is you don't know what the release name will be
until it's out there (or you try to guess ahead of time and are often wrong).

This makes talking about and planning for a release unnecessarily verbose. You
can only describe your releases in terms of relative time. Item A is going in
the next release. Or the release after next. Or three releases from now. It's
much easier to know the name of a release ahead of time.

I did away with semver for my company awhile ago, moved to dates for a little
while, and now just do plain numbers. It's basically just a simplified version
of semver without a distinction between MAJOR or MINOR patches. This works
just fine when you're building a web app and not a library to be consumed by
others.

------
dathinab
Semver is not about choice.

It's about conveiing when something might potentially have broken due to API
changes.

And it's about doing so in a way which can be interpreted by an algorithm.

------
golergka
There's one more situation where you should use semver: where you
simultaneously develop the next version, which will not be ready for release
in the next couple of weeks, and provide hotfixes to the public one. May be
the end user won't be making a decision which version to use, but your qa will
certainly experience both at the same time, so they should have some
understanding of what's the magic version of the product, aside from release
date.

------
lucideer
This is a very confused post.

The title is correct. It calls out that _individuals_ are _abusing_ semver,
rather than calling out semver itself.

Then it goes on to list examples of such abuse. Fine.

Then, it concludes by proposing to REPLACE SEMVER!!!??

At no point has the article called out any problems with semver itself, other
than people use it incorrectly.

Even if only 5% of people use semver correctly, that's still 5% of uses that
give more beneficial information than this proposed alternative.

~~~
majewsky
My guess is that if it were a reasoned argument for when to use semver and
when not to use it, it wouldn't be controversial enough to make the front
page.

The first third of the article is insightful. The rest is mostly bait.

------
dmitriid
I now prefer ComVer, "Compatible Versioning" [1][2]

[1] [https://gitlab.com/staltz/comver](https://gitlab.com/staltz/comver)

[2] [https://staltz.com/i-wont-use-semver-patch-versions-
anymore....](https://staltz.com/i-wont-use-semver-patch-versions-anymore.html)

~~~
smichel17
May I suggest my own invention, smver? It's MajorPatch.Minor, where Patch is
lettered. For example, this spec itself, which I wrote today, is at v0a.1. The
first stable version will be 1a.0.

Basically, it's the same principle as comver, where any breaking change must
increment the first identifier, but with some added metadata to hint how big
of a change the developer intended this to be. You can omit the patch if you
want, in release announcements, so marketing can have the "6.0 released!"
moment (I am considering omitting the patch letter for the first major
release, so 4a.0 follows 4.0).

------
jkmybffjill
Humans determining the difference between a major minor and patch is never
perfect. If we cannot rely on semver and can only trust a changelog, why
suffer the manual step in our CD? Just autoincrement and maintain a decent
changelog.

------
0xEA
Where i work we abuse semver but I hope in a good way. Major is wire api
break. Minor is effectively YYYYMMWW (we ship weekly) and patch is number of
commits off stable branch.

~~~
paulryanrogers
So not actually SemVer.

------
andrewstuart
I switched to integer version numbers.

------
louisch
Maybe use ISO8601 time instead so that timezones are accounted for (if team
members are in different parts of the globe).

------
lmm
Date is extremely noisy and doesn't tell you anything that (pseudo-) semver
wouldn't. If anything it tells you less. Why would I want to use 20 characters
when 7 or 8 will do the job?

Make sure you have a git tag corresponding to your release versions. That's
the main thing they're good for.

------
Snelius
I'm using semver with minor as date For example: 1.0.20200729

~~~
paulryanrogers
If skipping patch numbers I don't think this is actually SemVer. Rather it's a
custom versioning whose major and minor convention is similar. (Which is fine
just not SemVer.)

~~~
Snelius
Why it's not a semver? The minor is present and still increasing.

------
Kiro
They speak like they own the X.Y.Z format. I use it but I don't conform to
semver at all. Just leave me alone.

~~~
viraptor
I believe the article is specifically about semver, not X.Y.Z format. You can
have the format without the meaning. Linux uses X.Y.Z for example, but it's
explicitly not semver.

------
mikl
Using x.y.z version numbers does not imply semver.

I agree that semver as defined only really makes sense for libraries. When
working on internal code, “breaking changes” are rarely a concern.

We instead use it to mean <major overhaul>.<feature change>.<minor bugfix>.
That works well as semver-ish, and is more useful than just a date or a commit
hash.

------
rswail
Semantic versioning is about the _interface_. If there's no change to the
interface, there's no change to the semver.

You don't bump the semver because you've fixed internal server bugs, you don't
bump it if you've added logging to your code, you don't bump it if you've
refactored internally.

~~~
dragonwriter
> You don't bump the semver because you've fixed internal server bugs, you
> don't bump it if you've added logging to your code, you don't bump it if
> you've refactored internally.

All of those would be patch-level changes in semver (assuming they were in an
actual release.)

~~~
rswail
Not if they don't actually change the API. If you fix an internal server bug
that relates to a visible change in the API, then yes, it's a patch in the
semver.

If you change something internal that has nothing to do with a client's use of
your API, then there's no change to the semver.

Your package/container/program may change version in deployment, but that has
nothing to do with the API.

If I decide to move from redis to elasticache or mysql to postgres but my API
hasn't changed, that's not a change in the semver.

~~~
dragonwriter
> Not if they don't actually change the API.

If they don't effect behavior of the API, they'd be build-level, which is
optional in SemVer.

> If you fix an internal server bug that relates to a visible change in the
> API, then yes, it's a patch in the semver.

Visible changes to the API are SemVer minor if they are backward compatible,
SemVer major if they are not. The lower level fields of SemVer are for things
that don't change the expected behavior of the public API, including (at the
build level) those that don't effect visible behavior of the API.

SemVer is not API versioning, it's product versioning for a product that
implements an API. (I agree that something like SemVer used to version
independent APIs implemented by a product is in some respect a better idea
than SemVer itself, except that package management systems don't support API
identification and versioning in a way which would let it be useful in most
cases; SemVer is product versioning for the world where your product version
needs to both tell about product increments that don't effect the public API
and those that do.)

