[GH-ISSUE #241] Handling hotfix versions #5283

Closed
opened 2026-06-15 11:32:39 -05:00 by GiteaMirror · 46 comments
Owner

Originally created by @tomstreet on GitHub (Jan 18, 2015).
Original GitHub issue: https://github.com/semver/semver/issues/241

Is there (or should there be) a way to define a hotfix version?

Something like this:
1.0.0-hotfix.1 > 1.0.0
but
1.0.0-hotfix.1 < 1.0.1-beta.1 < 1.0.1

I get that the '-' is used for 'pre' versions, so maybe some other character for 'post/hotfix' versions?

Originally created by @tomstreet on GitHub (Jan 18, 2015). Original GitHub issue: https://github.com/semver/semver/issues/241 Is there (or should there be) a way to define a hotfix version? Something like this: 1.0.0-hotfix.1 > 1.0.0 but 1.0.0-hotfix.1 < 1.0.1-beta.1 < 1.0.1 I get that the '-' is used for 'pre' versions, so maybe some other character for 'post/hotfix' versions?
Author
Owner

@FichteFoll commented on GitHub (Jan 18, 2015):

For a hotfix, just increase patch.
So, 1.0.0 → 1.0.1

For post-releases (e.g. dev builds) see #200.

<!-- gh-comment-id:70410845 --> @FichteFoll commented on GitHub (Jan 18, 2015): For a hotfix, just increase patch. So, 1.0.0 → 1.0.1 For post-releases (e.g. dev builds) see #200.
Author
Owner

@tomstreet commented on GitHub (Jan 18, 2015):

I'm thinking about a scenario where you have already made a 1.0.0 release and a 1.0.1 release, then find an issue with the 1.0.0 release that needs to be hotfixed right now. So you pull down the 1.0.0 release code, hot fix it then need to release a 1.0.0-hotfix which can be used instead of 1.0.0.

<!-- gh-comment-id:70423817 --> @tomstreet commented on GitHub (Jan 18, 2015): I'm thinking about a scenario where you have already made a 1.0.0 release and a 1.0.1 release, then find an issue with the 1.0.0 release that needs to be hotfixed right now. So you pull down the 1.0.0 release code, hot fix it then need to release a 1.0.0-hotfix which can be used instead of 1.0.0.
Author
Owner

@FichteFoll commented on GitHub (Jan 18, 2015):

Sounds like a non-issue to me. You would release a new patch for a hotfix either way, so your "users" should be on 1.0.1 already. The only reason for them to not be on 1.0.1 is if you introduced some breaking changes or new functionality, in which case you should be on 2.0.0 or 1.1.0.

<!-- gh-comment-id:70424148 --> @FichteFoll commented on GitHub (Jan 18, 2015): Sounds like a non-issue to me. You would release a new patch for a hotfix either way, so your "users" should be on 1.0.1 already. The only reason for them to not be on 1.0.1 is if you introduced some breaking changes or new functionality, in which case you should be on 2.0.0 or 1.1.0.
Author
Owner

@crazedsanity commented on GitHub (Jan 19, 2015):

@tomstreet is there some scenario you can present that might clarify your problem? Maybe some clarification would help.

<!-- gh-comment-id:70507475 --> @crazedsanity commented on GitHub (Jan 19, 2015): @tomstreet is there some scenario you can present that might clarify your problem? Maybe some clarification would help.
Author
Owner

@tomstreet commented on GitHub (Jan 19, 2015):

@crazedsanity it's a problem we sometimes have where a customer doesn't want to upgrade their current version for whatever reason, but they want a specific issue fixing on the release they are using. They may be on 1.0.1 and the next patch release may be 1.0.5 but they just want the one fix applying to their current version without taking the other fixes that have been applied to the other releases.

This is quite rare, but it does happen, so just wondering the best way to handle it really.

<!-- gh-comment-id:70519488 --> @tomstreet commented on GitHub (Jan 19, 2015): @crazedsanity it's a problem we sometimes have where a customer doesn't want to upgrade their current version for whatever reason, but they want a specific issue fixing on the release they are using. They may be on 1.0.1 and the next patch release may be 1.0.5 but they just want the one fix applying to their current version without taking the other fixes that have been applied to the other releases. This is quite rare, but it does happen, so just wondering the best way to handle it really.
Author
Owner

@crazedsanity commented on GitHub (Jan 19, 2015):

Seems like the best way to resolve this problem, in a "perfect" world, would be to increment the patch version, exactly as @FichteFoll stated. Given this isn't a perfect world...

Appending meta data, such as "-hotfix.1" would fix it; if I'm not mistaken, 1.1.0-hotfix.1 > 1.1.1, right? They can upgrade to that specific version through whatever means is available.

That said, I would highly recommend that you encourage those customers to upgrade to the most recent patch version. Tossing out special hot fixes can lead to conflicts, where data gets changed one way (e.g. in 1.1.0-hotfix.1) and another way after the main line was patched (e.g. in 1.1.3). This can lead to a ripple effect that keeps the affected customer(s) from ever upgrading to the most recent version.

<!-- gh-comment-id:70526773 --> @crazedsanity commented on GitHub (Jan 19, 2015): Seems like the best way to resolve this problem, in a "perfect" world, would be to increment the patch version, exactly as @FichteFoll stated. Given this isn't a perfect world... Appending meta data, such as "-hotfix.1" would fix it; if I'm not mistaken, `1.1.0-hotfix.1 > 1.1.1`, right? They can upgrade to that specific version through whatever means is available. That said, I would _highly recommend_ that you encourage those customers to upgrade to the most recent patch version. Tossing out special hot fixes can lead to conflicts, where data gets changed one way (e.g. in `1.1.0-hotfix.1`) and another way after the main line was patched (e.g. in `1.1.3`). This can lead to a ripple effect that keeps the affected customer(s) from ever upgrading to the most recent version.
Author
Owner

@FichteFoll commented on GitHub (Jan 19, 2015):

Appending meta data, such as "-hotfix.1" would fix it; if I'm not mistaken, 1.1.0-hotfix.1 > 1.1.1, right?

No, metadata is signaled with the + sign, so it would be 1.1.0+with.hotfix.especially.for.you.my.dear.customer.x. Kind of. The other side of this is that, technically, metadata SHOULD be ignored when determining precedence, but you could ignore that clause if you really need it as it's not a requirement. Considering that you're likely not using a package manager, updater or something with version resolution you might just get away with it, but I also recommend you to encourage your users to upgrade. Maybe a silly version name like mine can help there. ;)

<!-- gh-comment-id:70536466 --> @FichteFoll commented on GitHub (Jan 19, 2015): > Appending meta data, such as "-hotfix.1" would fix it; if I'm not mistaken, 1.1.0-hotfix.1 > 1.1.1, right? No, metadata is signaled with the `+` sign, so it would be `1.1.0+with.hotfix.especially.for.you.my.dear.customer.x`. Kind of. The other side of this is that, technically, metadata SHOULD be ignored when determining precedence, but you _could_ ignore that clause if you really need it as it's not a requirement. Considering that you're likely not using a package manager, updater or something with version resolution you might just get away with it, but I also recommend you to encourage your users to upgrade. Maybe a silly version name like mine can help there. ;)
Author
Owner

@tomstreet commented on GitHub (Jan 20, 2015):

@FichteFoll agreed! Thanks for helping clarify.

<!-- gh-comment-id:70744981 --> @tomstreet commented on GitHub (Jan 20, 2015): @FichteFoll agreed! Thanks for helping clarify.
Author
Owner

@Anthropic commented on GitHub (Jun 25, 2015):

@tomstreet the company I work at adds a fourth number for hotfixes, not technically semver then I guess, but there's generally no other way given the structure of their pipeline as they number branches, so the next number is already taken and mentioned in bug trackers and other systems etc.. so when a major production issue occurs they chose to give it an extra number.

I guess it isn't overly important purely because it is an internal application. Not sure how they'd go trying to change, even if the app became public, the behaviour is too entrenched.

To be clear I'm not advocating for anything here, just saying what some companies must be doing.

<!-- gh-comment-id:115054244 --> @Anthropic commented on GitHub (Jun 25, 2015): @tomstreet the company I work at adds a fourth number for hotfixes, not technically semver then I guess, but there's generally no other way given the structure of their pipeline as they number branches, so the next number is already taken and mentioned in bug trackers and other systems etc.. so when a major production issue occurs they chose to give it an extra number. I guess it isn't overly important purely because it is an internal application. Not sure how they'd go trying to change, even if the app became public, the behaviour is too entrenched. To be clear **I'm not advocating for anything** here, just saying what some companies must be doing.
Author
Owner

@koenpeters commented on GitHub (Mar 18, 2016):

We actually run into this issue more often than we like. We developer software for a client and we do not control the deployment of this software. The development branch gets released every couple of weeks (with a semver version number) but the version that is in production may be a couple of versions behind. The customer may even choose to skip the production deployment of a couple of versions (for various reasons I will not go into now). I have experienced more than once that the version that is currently in production needs a fix (which may even be backwards incompatible, yeah really). These fixes cannot be versioned using semver because the newer versions already exist (we delivered them to the client already).

The current semver doesn't really take this scenario into account. We use an additional hotfix indication in some scenarios: major.minor.patch_hotfix. This hotfix is only used in the case an already delivered component needs to be changed and a newer version already exists that has a version number that would conflict with the semantic version of that change (see the table below for examples). This hotfix is not a number but a letter, starting with "a", if an additional hotfix is needed on this already hotfixed version this letter changes into "b", etc.

We currently use an underscore hoping that it won't break package managers like maven, npm, composer, gradle, cocoapods and carthage, but we're not sure to be honest. If you have a better proposal for a delimiter please let us know.

Since the hotfix letter does not show if the fix has breaking changes, adds new features or is only a patch, the release notes should make clear what the user can expect.

We use the following logic for versioning hotfixes:

Version that needs the fix Latest released version Version part that must change based on semantic versioning New version
1.0.0 1.0.0 major 2.0.0
minor 1.1.0
patch 1.0.1
1.0.0 1.1.0 major 1.0.0_a*
minor 1.0.0_a
patch 1.0.1
1.0.0 1.0.1 major 2.0.0**
minor 1.1.0**
patch 1.0.2**
1.0.0 1.1.1 major 1.0.0_a*
minor 1.0.0_a
patch 1.0.1
1.0.0 2.0.0 major 1.0.0_a
minor 1.1.0
patch 1.0.1
1.0.0_a any any 1.0.0_b

*) The semantic versioning schema would dictate that the new version should be higher than the latest version. The user however would expect that this new (higher) version would also include all the features that are in the latest release. Since this is not the case and to prevent these kind of "feature misunderstandings" we use hotfix naming.

**) In this case the latest release MUST be used as the source, since their APIs are identical. This is why we do not need a hotfix naming in this case.

<!-- gh-comment-id:198416146 --> @koenpeters commented on GitHub (Mar 18, 2016): We actually run into this issue more often than we like. We developer software for a client and we do not control the deployment of this software. The development branch gets released every couple of weeks (with a semver version number) but the version that is in production may be a couple of versions behind. The customer may even choose to skip the production deployment of a couple of versions (for various reasons I will not go into now). I have experienced more than once that the version that is currently in production needs a fix (which may even be backwards incompatible, yeah really). These fixes cannot be versioned using semver because the newer versions already exist (we delivered them to the client already). The current semver doesn't really take this scenario into account. We use an additional hotfix indication in some scenarios: major.minor.patch_hotfix. This hotfix is only used in the case an already delivered component needs to be changed and a newer version already exists that has a version number that would conflict with the semantic version of that change (see the table below for examples). This hotfix is not a number but a letter, starting with "a", if an additional hotfix is needed on this already hotfixed version this letter changes into "b", etc. We currently use an underscore hoping that it won't break package managers like maven, npm, composer, gradle, cocoapods and carthage, but we're not sure to be honest. If you have a better proposal for a delimiter please let us know. Since the hotfix letter does not show if the fix has breaking changes, adds new features or is only a patch, the release notes should make clear what the user can expect. We use the following logic for versioning hotfixes: | Version that needs the fix | Latest released version | Version part that must change based on semantic versioning | New version | | --- | --- | --- | --- | | 1.0.0 | 1.0.0 | major | 2.0.0 | | | | minor | 1.1.0 | | | | patch | 1.0.1 | | 1.0.0 | 1.1.0 | major | 1.0.0_a* | | | | minor | 1.0.0_a | | | | patch | 1.0.1 | | 1.0.0 | 1.0.1 | major | 2.0.0** | | | | minor | 1.1.0** | | | | patch | 1.0.2** | | 1.0.0 | 1.1.1 | major | 1.0.0_a* | | | | minor | 1.0.0_a | | | | patch | 1.0.1 | | 1.0.0 | 2.0.0 | major | 1.0.0_a | | | | minor | 1.1.0 | | | | patch | 1.0.1 | | 1.0.0_a | any | any | 1.0.0_b | *) The semantic versioning schema would dictate that the new version should be higher than the latest version. The user however would expect that this new (higher) version would also include all the features that are in the latest release. Since this is not the case and to prevent these kind of "feature misunderstandings" we use hotfix naming. **) In this case the latest release MUST be used as the source, since their APIs are identical. This is why we do not need a hotfix naming in this case.
Author
Owner

@watadarkstar commented on GitHub (May 18, 2020):

We use the semver spec with an additional HOTFIX version.

Given a version number MAJOR.MINOR.PATCH-hotfix.HOTFIX, increment the:

  • MAJOR version when you make incompatible API changes,
  • MINOR version when you add functionality in a backwards compatible manner, and
  • PATCH version when you make backwards compatible bug fixes.
  • HOTFIX version when you make a hot-fix to an existing released version.
<!-- gh-comment-id:630393623 --> @watadarkstar commented on GitHub (May 18, 2020): We use the semver spec with an additional HOTFIX version. Given a version number `MAJOR.MINOR.PATCH-hotfix.HOTFIX`, increment the: - `MAJOR` version when you make incompatible API changes, - `MINOR` version when you add functionality in a backwards compatible manner, and - `PATCH` version when you make backwards compatible bug fixes. - `HOTFIX` version when you make a hot-fix to an existing released version.
Author
Owner

@ljharb commented on GitHub (May 18, 2020):

https://github.com/semver/semver/issues/241#issuecomment-70424148 is still the right answer to me; I see no value in a "hotfix" - that's literally what patch is.

<!-- gh-comment-id:630394883 --> @ljharb commented on GitHub (May 18, 2020): https://github.com/semver/semver/issues/241#issuecomment-70424148 is still the right answer to me; I see no value in a "hotfix" - that's literally what patch is.
Author
Owner

@jwdonahue commented on GitHub (May 18, 2020):

There is nothing in the SemVer spec that precludes this version history:

1.0.0 // Contains bugs + 1 critical.
1.0.1 // Fixes some bugs, but not the critical bug.
1.0.2 // Fixes critical bug, but hasn't been tested with fixes in 1.0.1 so doesn't have those non-critical fixes.
1.0.3 // Includes all critical and non-critical fixes from 1.0.1 and 1.0.2

Naturally, the release notes in 1.0.2 should make it abundantly clear that it does not include early patches. The way SemVer works, no-one is going to pull another 1.0.0 if there are already patches for it. They are going to pull highest patch, unless they depend on your bugs or wish to reproduce them.

If you do not feel comfortable with the above scenario, don't use SemVer.

<!-- gh-comment-id:630405660 --> @jwdonahue commented on GitHub (May 18, 2020): There is nothing in the SemVer spec that precludes this version history: 1.0.0 // Contains bugs + 1 critical. 1.0.1 // Fixes some bugs, but not the critical bug. 1.0.2 // Fixes critical bug, but hasn't been tested with fixes in 1.0.1 so doesn't have those non-critical fixes. 1.0.3 // Includes all critical and non-critical fixes from 1.0.1 and 1.0.2 Naturally, the release notes in 1.0.2 should make it abundantly clear that it does not include early patches. The way SemVer works, no-one is going to pull another 1.0.0 if there are already patches for it. They are going to pull highest patch, unless they depend on your bugs or wish to reproduce them. If you do not feel comfortable with the above scenario, don't use SemVer.
Author
Owner

@jwdonahue commented on GitHub (May 18, 2020):

@tomstreet, unless you intend to issue a PR/RFC or have further questions, please close this issue at your earliest possible convenience.

<!-- gh-comment-id:630406863 --> @jwdonahue commented on GitHub (May 18, 2020): @tomstreet, unless you intend to issue a PR/RFC or have further questions, please close this issue at your earliest possible convenience.
Author
Owner

@watadarkstar commented on GitHub (May 18, 2020):

@jwdonahue This was insightful:

The way SemVer works, no-one is going to pull another 1.0.0 if there are already patches for it.

<!-- gh-comment-id:630408528 --> @watadarkstar commented on GitHub (May 18, 2020): @jwdonahue This was insightful: > The way SemVer works, no-one is going to pull another 1.0.0 if there are already patches for it.
Author
Owner

@alexandrtovmach commented on GitHub (Jun 10, 2020):

@tomstreet This issue seems resolved. Feel free to re-open if there still some questions

<!-- gh-comment-id:642117345 --> @alexandrtovmach commented on GitHub (Jun 10, 2020): @tomstreet This issue seems resolved. Feel free to re-open if there still some questions
Author
Owner

@jstafford5380 commented on GitHub (Jul 7, 2020):

Scenario I'm thinking of is doing a hotfix (critical patch) when there's already another patch (non-critical) coming in behind it. So if 1.0.0 is in production and broken, it needs a hotfix, but perhaps version 1.0.1 (non-critical bug patch) is already in the pipe. You'd have to stop that and fix everything to be 1.0.2.

<!-- gh-comment-id:655016411 --> @jstafford5380 commented on GitHub (Jul 7, 2020): Scenario I'm thinking of is doing a hotfix (critical patch) when there's already another patch (non-critical) coming in behind it. So if 1.0.0 is in production and broken, it needs a hotfix, but perhaps version 1.0.1 (non-critical bug patch) is already in the pipe. You'd have to stop that and fix everything to be 1.0.2.
Author
Owner

@ljharb commented on GitHub (Jul 7, 2020):

I'm not sure why you'd need to stop it; 1.0.2 would just contain whatever 1.0.1 did (along with the hotfix), and you'd deploy that.

<!-- gh-comment-id:655017293 --> @ljharb commented on GitHub (Jul 7, 2020): I'm not sure why you'd need to stop it; 1.0.2 would just contain whatever 1.0.1 did (along with the hotfix), and you'd deploy that.
Author
Owner

@jstafford5380 commented on GitHub (Jul 7, 2020):

I think you missed what I was describing. 1.0.2 doesn't exist at that point in time. 1.0.0 is in prod and needs a hotfix, and 1.0.1 is in the pipe and has code that may not be ready for release (in addition to the hotfix). If you do the hot fix using current semver, then the hotfix will be 1.0.1 which means the one that's already in the pipe is now tagged the wrong version.

<!-- gh-comment-id:655019067 --> @jstafford5380 commented on GitHub (Jul 7, 2020): I think you missed what I was describing. 1.0.2 doesn't exist at that point in time. 1.0.0 is in prod and needs a hotfix, and 1.0.1 is in the pipe and has code that may not be ready for release (in addition to the hotfix). If you do the hot fix using current semver, then the hotfix will be 1.0.1 which means the one that's already in the pipe is now tagged the wrong version.
Author
Owner

@ljharb commented on GitHub (Jul 7, 2020):

Why would v1.0.1 exist but not be ready for release? Assigning a version number is marking it as ready for release.

<!-- gh-comment-id:655019937 --> @ljharb commented on GitHub (Jul 7, 2020): Why would v1.0.1 exist but not be ready for release? Assigning a version number *is* marking it as ready for release.
Author
Owner

@jstafford5380 commented on GitHub (Jul 7, 2020):

Because of release management? They name the version as part of a planned release, list the changes and then teams begin the work and the work starts moving down the pipeline -- this is how things are kept in sync across the enterprise. So it starts off as feature branches and gets merged to master (e.g. Trunk based dev), and then when we have a candidate, it's cut with the version number (e.g. 1.0.1-rc.1) so that QA can review it and it can be staged for release to the public. What makes it ready for release is removing the candidate suffix (e.g. 1.0.1-rc.1 becomes 1.0.1 or 1.0.1).

So the point is that that 1.0.1 non-critical bug patch could be in QA pipe for 2 weeks or more before it's ready for release, depending on the situation.

<!-- gh-comment-id:655024439 --> @jstafford5380 commented on GitHub (Jul 7, 2020): Because of release management? They name the version as part of a planned release, list the changes and then teams begin the work and the work starts moving down the pipeline -- this is how things are kept in sync across the enterprise. So it starts off as feature branches and gets merged to master (e.g. Trunk based dev), and then when we have a candidate, it's cut with the version number (e.g. 1.0.1-rc.1) so that QA can review it and it can be staged for release to the public. What makes it ready for release is removing the candidate suffix (e.g. 1.0.1-rc.1 becomes 1.0.1 or 1.0.1). So the point is that that 1.0.1 non-critical bug patch could be in QA pipe for 2 weeks or more before it's ready for release, depending on the situation.
Author
Owner

@ljharb commented on GitHub (Jul 7, 2020):

That seems like it should be a prerelease, until the very instant it's ready to deploy - meaning the non-critical one might be 1.0.1-rc.0, and the critical one might be 1.0.1-hotfix.0, and if the hotfix lands first, then 1.0.1-rc.0 needs to be removed from the pipeline and replaced with an 1.0.2-rc.0 that includes both the hotfix and the non-critical change.

<!-- gh-comment-id:655026632 --> @ljharb commented on GitHub (Jul 7, 2020): That seems like it should be a prerelease, until the very instant it's ready to deploy - meaning the non-critical one might be `1.0.1-rc.0`, and the critical one might be `1.0.1-hotfix.0`, and if the hotfix lands first, then 1.0.1-rc.0 needs to be removed from the pipeline and replaced with an 1.0.2-rc.0 that includes both the hotfix and the non-critical change.
Author
Owner

@jstafford5380 commented on GitHub (Jul 7, 2020):

Yes, that's kind of my point. You have to disrupt the pipeline and retag, update release notes, etc. In larger organizations, that's not always as trivial as it sounds, and it's likely to scramble up your artifact repo and significantly complicate your CICD process

<!-- gh-comment-id:655028541 --> @jstafford5380 commented on GitHub (Jul 7, 2020): Yes, that's kind of my point. You have to disrupt the pipeline and retag, update release notes, etc. In larger organizations, that's not always as trivial as it sounds, and it's likely to scramble up your artifact repo and significantly complicate your CICD process
Author
Owner

@ljharb commented on GitHub (Jul 7, 2020):

Perhaps that may be an indicator that semver isn't an appropriate choice for a deployed app that needs hotfixes and has a two-week deploy pipeline :-)

<!-- gh-comment-id:655030133 --> @ljharb commented on GitHub (Jul 7, 2020): Perhaps that may be an indicator that semver isn't an appropriate choice for a deployed app that needs hotfixes and has a two-week deploy pipeline :-)
Author
Owner

@khuttun commented on GitHub (Apr 23, 2021):

Just my 2¢ on how to handle this: when we make the first release from a new release branch, the MAJOR and/or MINOR version number is always incremented and PATCH is set to 0. This reserves the PATCH version to be used only for hotfix releases from existing release branches.

<!-- gh-comment-id:825461834 --> @khuttun commented on GitHub (Apr 23, 2021): Just my 2¢ on how to handle this: when we make the first release from a new release branch, the MAJOR and/or MINOR version number is always incremented and PATCH is set to 0. This reserves the PATCH version to be used only for hotfix releases from existing release branches.
Author
Owner

@cpascual commented on GitHub (Apr 28, 2021):

when we make the first release from a new release branch, the MAJOR and/or MINOR version number is always incremented and PATCH is set to 0

But doesn't this break the assumption that you communicate the type of change via the component changed in the version?

In other words, if my release is bugfix only and not adding new functionality, would it be right (in the semver sense) to increment MINOR instead of PATCH?

<!-- gh-comment-id:828343567 --> @cpascual commented on GitHub (Apr 28, 2021): > when we make the first release from a new release branch, the MAJOR and/or MINOR version number is always incremented and PATCH is set to 0 But doesn't this break the assumption that you communicate the type of change via the component changed in the version? In other words, if my release is bugfix only and not adding new functionality, would it be right (in the semver sense) to increment MINOR instead of PATCH?
Author
Owner

@ljharb commented on GitHub (Apr 28, 2021):

Yes, that’s perfectly fine - you can always overdo it. You can increment the major even if there’s no breaking changes if you want too.

<!-- gh-comment-id:828476185 --> @ljharb commented on GitHub (Apr 28, 2021): Yes, that’s perfectly fine - you can always overdo it. You can increment the major even if there’s no breaking changes if you want too.
Author
Owner

@michael8090 commented on GitHub (Jul 4, 2022):

@tomstreet This issue seems resolved. Feel free to re-open if there still some questions

I'm not sure if it's resolved. We run into the same problem recently and could not get a working solution that works well with ranged version. We end up to releasing 1.1.1-hotfix.1 of the library and setting the precise version number in the package.json of the app, which makes the version range useless...

<!-- gh-comment-id:1173489532 --> @michael8090 commented on GitHub (Jul 4, 2022): > @tomstreet This issue seems resolved. Feel free to re-open if there still some questions I'm not sure if it's resolved. We run into the same problem recently and could not get a working solution that works well with ranged version. We end up to releasing 1.1.1-hotfix.1 of the library and setting the precise version number in the package.json of the app, which makes the version range useless...
Author
Owner

@jeacott1 commented on GitHub (Mar 4, 2023):

@FichteFoll
I run into this all the time. semver isnt just for rapidly iterating software where the vendor has control over the deployment.
Imagine I have software released every 3 months, and various clients are running various versions. It can also take months for a client to run their own UAT and get newer versions into production. We need to maintain each of those old versions for a period too.

Now lets say we are up to version 2.0.0 on main, but also have 1.0.0, 1.3.0, 1.9.5 in the wild.
theres a critical bug in 1.3.0 we need to hotfix, but theres already a 1.3.1 on main and in our artifact repo so we cant create a new one of those. - I believe this is the exact usecase described by many on this thread. You cant just increment the patch number! if I add a 1.3.27 so it doesnt clash then that version 'appears' to be in the mainline chain of 1.3.x - but it isnt! how would we ever identify it? Also how would you ever try to get something like conventional commits to understand what latest is?

All that's required here is to alter the semver spec such that some variant of the pre-release meta/qualifiers are officially recognised as > release-version.
for my money I'd suggest marking a post-release meta with '-' instead of the '+' and call it job done.

<!-- gh-comment-id:1454338489 --> @jeacott1 commented on GitHub (Mar 4, 2023): @FichteFoll I run into this all the time. semver isnt just for rapidly iterating software where the vendor has control over the deployment. Imagine I have software released every 3 months, and various clients are running various versions. It can also take months for a client to run their own UAT and get newer versions into production. We need to maintain each of those old versions for a period too. Now lets say we are up to version 2.0.0 on main, but also have 1.0.0, 1.3.0, 1.9.5 in the wild. theres a critical bug in 1.3.0 we need to hotfix, but theres already a 1.3.1 on main and in our artifact repo so we cant create a new one of those. - I believe this is the exact usecase described by many on this thread. You cant just increment the patch number! if I add a 1.3.27 so it doesnt clash then that version 'appears' to be in the mainline chain of 1.3.x - but it isnt! how would we ever identify it? Also how would you ever try to get something like conventional commits to understand what latest is? All that's required here is to alter the semver spec such that some variant of the pre-release meta/qualifiers are officially recognised as > release-version. for my money I'd suggest marking a post-release meta with '-' instead of the '+' and call it job done.
Author
Owner

@ljharb commented on GitHub (Mar 4, 2023):

@jeacott1 someone on 1.3.0 should update to 1.3.1, and then to your fixed 1.3.2.

"Lines" that should be maintained are major or minor lines, not patch.

<!-- gh-comment-id:1454466908 --> @ljharb commented on GitHub (Mar 4, 2023): @jeacott1 someone on 1.3.0 should update to 1.3.1, and then to your fixed 1.3.2. "Lines" that should be maintained are major or minor lines, not patch.
Author
Owner

@FichteFoll commented on GitHub (Mar 5, 2023):

@jeacott1, @ljharb is right. SemVer does not consider for you to release a version between 1.3.0 and 1.3.1 because nobody who is on 1.3.0 should not want to update to 1.3.1. Their support branch is 1.3 (not 1.3.0) and they should ensure to update to the latest version of this branch. As such, if 1.3.1 exists while they are on 1.3.0, they are already behind and should update because that's what they need to do to get the latest bug fixes. Afterwards, they can update to 1.3.2 with the latest fixes.

You cant just increment the patch number! if I add a 1.3.27 so it doesnt clash then that version 'appears' to be in the mainline chain of 1.3.x - but it isnt!

If 1.3.1 is not a patch-level update for 1.3.0 (i.e. part of the 1.3 branch), SemVer was violated by the publisher and the version should be deleted/withdrawn, accompanied by another patch release that sets it right.

<!-- gh-comment-id:1455076011 --> @FichteFoll commented on GitHub (Mar 5, 2023): @jeacott1, @ljharb is right. SemVer does not consider for you to release a version between 1.3.0 and 1.3.1 because nobody who is on 1.3.0 should *not* want to update to 1.3.1. Their support branch is 1.3 (not 1.3.0) and they should ensure to update to the latest version of this branch. As such, if 1.3.1 exists while they are on 1.3.0, they are already behind and should update because that's what they need to do to get the latest bug fixes. Afterwards, they can update to 1.3.2 with the latest fixes. > You cant just increment the patch number! if I add a 1.3.27 so it doesnt clash then that version 'appears' to be in the mainline chain of 1.3.x - but it isnt! If 1.3.1 is not a patch-level update for 1.3.0 (i.e. part of the 1.3 branch), SemVer was violated by the publisher and the version should be deleted/withdrawn, accompanied by another patch release that sets it right.
Author
Owner

@jeacott1 commented on GitHub (Mar 6, 2023):

@ljharb that doesnt always work in practice - there are lots of real world issues that prevent that from being as clean as you imagine.
I'd like to say, sure, lets not maintain a patch line, but in practice when a customer has their own UAT that takes a long time to complete and requires more consideration for every patch applied, we need to be able to mitigate that sometimes.

@FichteFoll I think you misunderstand me. 1.3.1 is definitely a patch version for 1.3.0
imagine for whatever reason we embed some other moniker in the code along with the release number - like vista, or 2000.
you can argue its a bad idea for many reasons, but lets say the team went with repeatable builds and the source is everything.
version 1.3.0 has another property committed called '2022-03', and we have 1.3.1, and 1.3.2 on main with the same moniker. 1.3.3 updates this to '2022-06'. a few versions pass and we are at 1.5.0 but 2022-06 isn't released to any clients yet. - now I need to provide a hotfix to the 1.3 line.
if I first update to 1.3.3, and add my fix as 1.3.4 I also have to remember to patch this moniker back to 2022-03. maybe its not that simple, maybe there are tons of outliers to look out for.

I think semver on this point is getting in its own way trying to be too prescriptive about how real world things have to work sometimes.

<!-- gh-comment-id:1455406321 --> @jeacott1 commented on GitHub (Mar 6, 2023): @ljharb that doesnt always work in practice - there are lots of real world issues that prevent that from being as clean as you imagine. I'd like to say, sure, lets not maintain a patch line, but in practice when a customer has their own UAT that takes a long time to complete and requires more consideration for every patch applied, we need to be able to mitigate that sometimes. @FichteFoll I think you misunderstand me. 1.3.1 is definitely a patch version for 1.3.0 imagine for whatever reason we embed some other moniker in the code along with the release number - like vista, or 2000. you can argue its a bad idea for many reasons, but lets say the team went with repeatable builds and the source is everything. version 1.3.0 has another property committed called '2022-03', and we have 1.3.1, and 1.3.2 on main with the same moniker. 1.3.3 updates this to '2022-06'. a few versions pass and we are at 1.5.0 but 2022-06 isn't released to any clients yet. - now I need to provide a hotfix to the 1.3 line. if I first update to 1.3.3, and add my fix as 1.3.4 I also have to remember to patch this moniker back to 2022-03. maybe its not that simple, maybe there are tons of outliers to look out for. I think semver on this point is getting in its own way trying to be too prescriptive about how real world things have to work sometimes.
Author
Owner

@ljharb commented on GitHub (Mar 6, 2023):

@jeacott1 then for your use case, semver isn't appropriate. the things you're waving off as "you can argue its a bad idea" aren't a question of good or bad - doing that invalidates semver and thus, you'll have to select or create your own versioning scheme. if you want to use semver, you simply can't do that.

<!-- gh-comment-id:1455481275 --> @ljharb commented on GitHub (Mar 6, 2023): @jeacott1 then for your use case, semver isn't appropriate. the things you're waving off as "you can argue its a bad idea" aren't a question of good or bad - doing that *invalidates semver* and thus, you'll have to select or create your own versioning scheme. if you want to use semver, you simply *can't do that*.
Author
Owner

@FichteFoll commented on GitHub (Mar 6, 2023):

I also have to remember to patch this moniker back to 2022-03

I think I missed where this requirement comes from because 1.3.3 is supposedly already using 2022-06 so I'm not sure why 1.3.4 would need to patch back to 2022-03.

<!-- gh-comment-id:1455945590 --> @FichteFoll commented on GitHub (Mar 6, 2023): > I also have to remember to patch this moniker back to 2022-03 I think I missed where this requirement comes from because 1.3.3 is supposedly already using 2022-06 so I'm not sure why 1.3.4 would need to patch back to 2022-03.
Author
Owner

@jeacott1 commented on GitHub (Mar 7, 2023):

@FichteFoll I'm resigned that this isnt going to change, but just so you understand, 1.3.4 is a patch of a released version. the customer does not yet have 2022-06, and wont until we provide it at the agreed milestone with whatever else it was supposed to include. - at the point we need the hotfix we cant just provide something that claims to be 2022-06.
The other reason we dont want to take whatever patch fixes come along for the ride from main in a strictly semver view of the world when we provide a hotfix, is because one of those patches might have been a large refactor and suddenly the scope for potential issues to be discovered by the client has expanded a lot. They are paying the bills, we need to keep their workload for such things as small as possible.

<!-- gh-comment-id:1457518790 --> @jeacott1 commented on GitHub (Mar 7, 2023): @FichteFoll I'm resigned that this isnt going to change, but just so you understand, 1.3.4 is a patch of a released version. the customer does not yet have 2022-06, and wont until we provide it at the agreed milestone with whatever else it was supposed to include. - at the point we need the hotfix we cant just provide something that claims to be 2022-06. The other reason we dont want to take whatever patch fixes come along for the ride from main in a strictly semver view of the world when we provide a hotfix, is because one of those patches might have been a large refactor and suddenly the scope for potential issues to be discovered by the client has expanded a lot. They are paying the bills, we need to keep their workload for such things as small as possible.
Author
Owner

@FichteFoll commented on GitHub (Mar 7, 2023):

Thanks for clarifying.

It appears you are in a spot where you cannot adhere to semver anymore. As a result, you may

  1. release a special version for this client only and name it 1.3.2+hotfix.1.for.client.a or similar, if you must use a syntactically valid semver and only open this for that one client
  2. release a pre-release version of some future version, e.g. 1.3.4-hotfix.1.3.2, and only open this for that one client
  3. do whatever because you can't adhere to semver anymore, e.g. create a separate 1.3.3 release for your client that is not the same as the 1.3.3 for others (wouldn't recommend it because it will lead to confusion)

In general, what I believe should have happened is that you should have created a new minor release train when you updated to 2022-06 if you could have expected a valid use case of the older 2022-03 feature so that you would be able to still provide hotfixes for the old feature.

<!-- gh-comment-id:1458222309 --> @FichteFoll commented on GitHub (Mar 7, 2023): Thanks for clarifying. It appears you are in a spot where you cannot adhere to semver anymore. As a result, you may 1. release a special version for this client only and name it `1.3.2+hotfix.1.for.client.a` or similar, if you must use a syntactically valid semver and only open this for that one client 2. release a pre-release version of some future version, e.g. `1.3.4-hotfix.1.3.2`, and only open this for that one client 3. do whatever because you can't adhere to semver anymore, e.g. create a separate 1.3.3 release for your client that is not the same as the 1.3.3 for others (wouldn't recommend it because it will lead to confusion) In general, what I believe should have happened is that you should have created a new minor release train when you updated to 2022-06 if you could have expected a valid use case of the older 2022-03 feature so that you would be able to still provide hotfixes for the old feature.
Author
Owner

@jeacott1 commented on GitHub (Mar 7, 2023):

@FichteFoll yeah thats pretty much what I've done.
just to note "if you could have expected a valid use case of the older 2022-03 feature so that you would be able to still provide hotfixes for the old feature." - in this case it was train of patches, not features. should a bump of a pretty version constitute a feature? maybe so.
I guess my overarching point is that semver and other very prescriptive standards are often very difficult to stick to in the real world. In my view instead of the very idealistic path chosen, a slightly more pragmatic approach would yield wider adoption.
adding an option to parse -* as post release wrt version ordering would make compatibility with other standards like maven easier and offer options where otherwise the only real option is to abandon the standard.

thank you for the conversation and your advice.

<!-- gh-comment-id:1458978086 --> @jeacott1 commented on GitHub (Mar 7, 2023): @FichteFoll yeah thats pretty much what I've done. just to note "if you could have expected a valid use case of the older 2022-03 feature so that you would be able to still provide hotfixes for the old feature." - in this case it was train of patches, not features. should a bump of a pretty version constitute a feature? maybe so. I guess my overarching point is that semver and other very prescriptive standards are often very difficult to stick to in the real world. In my view instead of the very idealistic path chosen, a slightly more pragmatic approach would yield wider adoption. adding an option to parse -* as post release wrt version ordering would make compatibility with other standards like maven easier and offer options where otherwise the only real option is to abandon the standard. thank you for the conversation and your advice.
Author
Owner

@ljharb commented on GitHub (Mar 7, 2023):

There's few things with much wider adoption than semver, so I think the current level of pragmatism is pretty appropriate.

<!-- gh-comment-id:1458979287 --> @ljharb commented on GitHub (Mar 7, 2023): There's few things with much wider adoption than semver, so I think the current level of pragmatism is pretty appropriate.
Author
Owner

@steveklabnik commented on GitHub (Mar 9, 2023):

I guess my overarching point is that semver and other very prescriptive standards are often very difficult to stick to in the real world.

SemVer was created by describing what the Ruby community was doing with versions ten (or twenty? gosh I'm old) years ago. It came out of real-world usage, not the other way around.

<!-- gh-comment-id:1462684858 --> @steveklabnik commented on GitHub (Mar 9, 2023): > I guess my overarching point is that semver and other very prescriptive standards are often very difficult to stick to in the real world. SemVer was created by describing what the Ruby community was doing with versions ten (or twenty? gosh I'm old) years ago. It came out of real-world usage, not the other way around.
Author
Owner

@jeacott1 commented on GitHub (Mar 9, 2023):

@steveklabnik I'm aware, I'm older than that myself - and I find the semantics assigned to version components incredibly useful.
Thats not to say the spec couldn't be tweaked.

<!-- gh-comment-id:1462939850 --> @jeacott1 commented on GitHub (Mar 9, 2023): @steveklabnik I'm aware, I'm older than that myself - and I find the semantics assigned to version components incredibly useful. Thats not to say the spec couldn't be tweaked.
Author
Owner

@StFS commented on GitHub (Jun 11, 2024):

Skimming through the conversations on this issue I understand that my 2 cents won't change anything but I'd like to add them nevertheless.

A concrete example where this is a real issue is when you are in a highly regulated industry. Contracts with customers stipulate that any upgrades to the system must be communicated in advance (let's say 3 week notice).

We release ComponentA v1.2.3 to prod and then start working on v1.2.4 internally. When we want to release v1.2.4 we must communicate that with 3 week notice. Let's say we've done that yesterday but all of a sudden a serious security issue pops up that requires us to patch the prod system immediately (there are safeguards in customer contracts for this, critical security patches may be deployed without prior communication but of course, the customer must be notified ASAP). But this results in us having to release v1.2.5 and put that on prod (as a hotfix for 1.2.3)... and worst case scenario, if 1.2.4 is far along in the validation process, we will need to issue 1.2.6 as a replacement for that. So we end up in a situation where version continuity is broken, 1.2.4 does not contain the hotfix that has been issued for 1.2.3 and 1.2.5 does not contain changes that are included in 1.2.4.

So there are real world scenarios where this is an issue. And while I understand that you can say that SemVer should not be used here, I would argue, given the wide spread of SemVer, that it would be very desirable that it had some mechanism that would support this use case somehow.

I think, rather than having some "magic" suffix like "-hotfix.1" which behaves differently than other suffixes, the cleaner solution would be to add a fourth component to the version number so 1.2.3.1 would be a hotfix version for 1.2.3 and 1.2.4.1 a hotfix for 1.2.4 like someone suggested here above.

<!-- gh-comment-id:2160988997 --> @StFS commented on GitHub (Jun 11, 2024): Skimming through the conversations on this issue I understand that my 2 cents won't change anything but I'd like to add them nevertheless. A concrete example where this is a real issue is when you are in a highly regulated industry. Contracts with customers stipulate that any upgrades to the system must be communicated in advance (let's say 3 week notice). We release ComponentA v1.2.3 to prod and then start working on v1.2.4 internally. When we want to release v1.2.4 we must communicate that with 3 week notice. Let's say we've done that yesterday but all of a sudden a serious security issue pops up that requires us to patch the prod system immediately (there are safeguards in customer contracts for this, critical security patches may be deployed without prior communication but of course, the customer must be notified ASAP). But this results in us having to release v1.2.5 and put that on prod (as a hotfix for 1.2.3)... and worst case scenario, if 1.2.4 is far along in the validation process, we will need to issue 1.2.6 as a replacement for that. So we end up in a situation where version continuity is broken, 1.2.4 does not contain the hotfix that has been issued for 1.2.3 and 1.2.5 does not contain changes that are included in 1.2.4. So there _are_ real world scenarios where this is an issue. And while I understand that you can say that SemVer should not be used here, I would argue, given the wide spread of SemVer, that it would be very desirable that it had some mechanism that would support this use case somehow. I think, rather than having some "magic" suffix like "-hotfix.1" which behaves differently than other suffixes, the cleaner solution would be to add a fourth component to the version number so 1.2.3.1 would be a hotfix version for 1.2.3 and 1.2.4.1 a hotfix for 1.2.4 like someone suggested here above.
Author
Owner

@cpascual commented on GitHub (Jun 11, 2024):

Hi @StFS . I became frustrated long ago by the response to what IMHO is an obvious use case, with a sensible backwards-compatible solution which is ignored by semver. Our solution, back then, was to document the following in our project for the version:

This project uses PEP440 versioning where released versions start with 3 dot separated numbers (MAJOR.MINOR.PATCH), which should be interpreted as their homonym components in Semantic Versioning.

The advantages:

  • This wording supports the hotfix and support/legacy branching use cases, while retaining the value of the well known semantics for the MAJOR.MINOR.PATCH and referencing well documented version conventions (PEP440 and semver)
  • You can still use a normal semver-compatible version, and add the fourth number only when needed. See for example, our changelog, where we have: ... 4.7.0 -> 4.7.1 -> 4.7.1.1 -> 4.8.0 -> 4.8.1 -> 5.0.0 -> 5.0.0.1 -> 5.1.4 ...
  • Most generic versioning tools (such as bumpversion or GNU/Linux distro packaging tools) either support this scheme out of the box or they can be trivially configured to support it. And for python projects, this is in fact the default scheme assumed by the official tools
<!-- gh-comment-id:2161483590 --> @cpascual commented on GitHub (Jun 11, 2024): Hi @StFS . I became frustrated long ago by the response to what IMHO is an obvious use case, with a sensible backwards-compatible solution which is ignored by semver. Our solution, back then, was to [document the following in our project](https://gitlab.com/taurus-org/taurus/-/blob/develop/CHANGELOG.md) for the version: > This project uses [PEP440](https://www.python.org/dev/peps/pep-0440) versioning where released versions start with 3 dot separated numbers (MAJOR.MINOR.PATCH), which should be interpreted as their homonym components in [Semantic Versioning](http://semver.org/). The advantages: - This wording supports the hotfix and support/legacy branching use cases, while retaining the value of the well known semantics for the MAJOR.MINOR.PATCH and referencing well documented version conventions (PEP440 and semver) - You can still use a normal semver-compatible version, and add the fourth number **only when needed**. See for example, [our changelog](https://gitlab.com/taurus-org/taurus/-/blob/develop/CHANGELOG.md), where we have: ... `4.7.0` -> `4.7.1` -> **`4.7.1.1`** -> `4.8.0` -> `4.8.1` -> `5.0.0` -> **`5.0.0.1`** -> `5.1.4` ... - Most generic versioning tools (such as bumpversion or GNU/Linux distro packaging tools) either support this scheme out of the box or they can be trivially configured to support it. And for python projects, this is in fact the default scheme assumed by the official tools
Author
Owner

@jeacott1 commented on GitHub (Jun 12, 2024):

@cpascual @StFS an extra integer makes the versions look like windows version numbers which have entirely different semantics. From my pov a single extra int just doesn't offer enough flexibility. The spec already has a '+', but it only marks pre-release. adding a '-' option would allow you to do your thing and me to do mine, and nobody currently using semver would be affected at all.

<!-- gh-comment-id:2161945420 --> @jeacott1 commented on GitHub (Jun 12, 2024): @cpascual @StFS an extra integer makes the versions look like windows version numbers which have entirely different semantics. From my pov a single extra int just doesn't offer enough flexibility. The spec already has a '+', but it only marks pre-release. adding a '-' option would allow you to do your thing and me to do mine, and nobody currently using semver would be affected at all.
Author
Owner

@StFS commented on GitHub (Jun 12, 2024):

The spec already has a '+', but it only marks pre-release. adding a '-' option would allow you to do your thing and me to do mine, and nobody currently using semver would be affected at all.

Sorry, I must be missing something... but semver already defines a '-' as a pre-release (see https://semver.org/#backusnaur-form-grammar-for-valid-semver-versions), '+' is designated as a prefix for a build number. So both of those are already reserved it seems? Unless, like I said, I must be missing something.

<!-- gh-comment-id:2162400800 --> @StFS commented on GitHub (Jun 12, 2024): > The spec already has a '+', but it only marks pre-release. adding a '-' option would allow you to do your thing and me to do mine, and nobody currently using semver would be affected at all. Sorry, I must be missing something... but semver already defines a '-' as a pre-release (see https://semver.org/#backusnaur-form-grammar-for-valid-semver-versions), '+' is designated as a prefix for a build number. So both of those are already reserved it seems? Unless, like I said, I must be missing something.
Author
Owner

@jeacott1 commented on GitHub (Jun 13, 2024):

@StFS you are correct that there is already a '-' designating a pre-release. re-reading my own post above I said

all that's required here is to alter the semver spec such that some variant of the pre-release meta/qualifiers are officially recognised as > release-version.
for my money I'd suggest marking a post-release meta with '-' instead of the '+' and call it job done.

I think I was thinking that the + was positional, however given that the hyphen pre-release is optional just switching the + wont work. - perhaps a double '--' to mark a post-release option instead of '-' for pre-release.

<!-- gh-comment-id:2164231659 --> @jeacott1 commented on GitHub (Jun 13, 2024): @StFS you are correct that there is already a '-' designating a pre-release. re-reading my own post above I said > all that's required here is to alter the semver spec such that some variant of the pre-release meta/qualifiers are officially recognised as > release-version. > for my money I'd suggest marking a post-release meta with '-' instead of the '+' and call it job done. I think I was thinking that the + was positional, however given that the hyphen pre-release is optional just switching the + wont work. - perhaps a double '--' to mark a post-release option instead of '-' for pre-release.
Author
Owner

@StFS commented on GitHub (Jun 13, 2024):

perhaps a double '--' to mark a post-release option instead of '-' for pre-release.

ehh... then I would at least personally much prefer using the 1.2.3.1 format. Even if it resembles windows version numbering that doesn't mean Microsoft has any exclusive rights on this format. I mean, the three number format is also used by a multitude of software components and although the SemVer connotation is usually associated with it, it's certainly not always the case. So even with the three number format, there is ambiguity to some extent as to what that may mean exactly. Bottom line is that you always need to look into what version numbers mean in the software you're looking at.

<!-- gh-comment-id:2165112353 --> @StFS commented on GitHub (Jun 13, 2024): > perhaps a double '--' to mark a post-release option instead of '-' for pre-release. ehh... then I would at least personally much prefer using the `1.2.3.1` format. Even if it resembles windows version numbering that doesn't mean Microsoft has any exclusive rights on this format. I mean, the three number format is also used by a multitude of software components and although the SemVer connotation is _usually_ associated with it, it's certainly not always the case. So even with the three number format, there is ambiguity to some extent as to what that may mean exactly. Bottom line is that you always need to look into what version numbers mean in the software you're looking at.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/semver#5283