[GH-ISSUE #532] Supporting multiple versions and backporting fixes that introduce features or break things #7366

Open
opened 2026-06-20 17:23:03 -05:00 by GiteaMirror · 11 comments
Owner

Originally created by @claell on GitHub (Sep 13, 2019).
Original GitHub issue: https://github.com/semver/semver/issues/532

This might have been asked already, I did a deep search trying to identify similar issues, but don't think that has been answered already. If I am wrong, please link that answer and I will close this.

This issue is not theoretical, but has a real background. It was brought up by the OpenSSL team who cannot use Semver mainly because of this particular issue. It has been broken down pretty good in this comment: https://github.com/openssl/openssl/issues/5042#issuecomment-494534534

The issue is that when fixing things or contiued support it might be reqiured to add some features (or even breaking changes). This would bump the MINOR or MAJOR version number. The problem developing multiple versions at the same time is that bumping those numbers is not trivial as there are already versions existing using the following numbers.

Originally created by @claell on GitHub (Sep 13, 2019). Original GitHub issue: https://github.com/semver/semver/issues/532 This might have been asked already, I did a deep search trying to identify similar issues, but don't think that has been answered already. If I am wrong, please link that answer and I will close this. This issue is not theoretical, but has a real background. It was brought up by the OpenSSL team who cannot use Semver mainly because of this particular issue. It has been broken down pretty good in this comment: https://github.com/openssl/openssl/issues/5042#issuecomment-494534534 The issue is that when fixing things or contiued support it might be reqiured to add some features (or even breaking changes). This would bump the MINOR or MAJOR version number. The problem developing multiple versions at the same time is that bumping those numbers is not trivial as there are already versions existing using the following numbers.
GiteaMirror added the question label 2026-06-20 17:23:03 -05:00
Author
Owner

@ljharb commented on GitHub (Sep 13, 2019):

If you have a v1 line and a v2 line, and you need to add a breaking change to v1, what prevents making a v3 (v2, plus the fix) and those users having to upgrade to it?

(eg I'm not clear on what sort of breaking change bugfix would be "ok" for v1 users to accept, but the breaking changes in v2 would not be "ok" for them to also accept)

<!-- gh-comment-id:531323837 --> @ljharb commented on GitHub (Sep 13, 2019): If you have a v1 line and a v2 line, and you need to add a breaking change to v1, what prevents making a v3 (v2, plus the fix) and those users having to upgrade to it? (eg I'm not clear on what sort of breaking change bugfix would be "ok" for v1 users to accept, but the breaking changes in v2 would not be "ok" for them to also accept)
Author
Owner

@kroeckx commented on GitHub (Sep 14, 2019):

People do not want to upgrade to the latest version for various reasons. Like you point out, distro's for instance just patch the kernel and don't just provide a newer kernel version. To better support users that do not want to upgrade, multiple versions have a long term support, so that all distro's don't need to backport and maintain their own patches. In theory such old version just get bug fixes, they don't get new features. But sometimes it's necessary to add a new feature in an old release. That feature does get added to all supported versions that need it. If you're in such a situation, it's likely that you can't actually follow the semver rules.

(I'm not suggestion that the semver rules need to change, just explaining why it doesn't work for everybody.)

<!-- gh-comment-id:531464403 --> @kroeckx commented on GitHub (Sep 14, 2019): People do not want to upgrade to the latest version for various reasons. Like you point out, distro's for instance just patch the kernel and don't just provide a newer kernel version. To better support users that do not want to upgrade, multiple versions have a long term support, so that all distro's don't need to backport and maintain their own patches. In theory such old version just get bug fixes, they don't get new features. But sometimes it's necessary to add a new feature in an old release. That feature does get added to all supported versions that need it. If you're in such a situation, it's likely that you can't actually follow the semver rules. (I'm not suggestion that the semver rules need to change, just explaining why it doesn't work for everybody.)
Author
Owner

@kroeckx commented on GitHub (Sep 14, 2019):

As Debian Developer, I perfectly know how distributions work.
Since the Linux kernel started to have long term support for the
kernels, Debian has picked one of those longterm kernels for the
release. But even the kernel can't keep the ABI stable. Debian just
had a stable release update that changed from:
linux-image-4.19.0-5-amd64 4.19.37-5+deb10u2
to:
linux-image-4.19.0-6-amd64 4.19.67-2

Notice the change from -5 to -6, because it's not compatible
anymore.

But the important part is that Debian switched to an upstream
kernel that is supported upstream and no longer needs to maintain
it's own fork of some random release. There is little point in
having all distro's do the same work when you can just do it once
upstream.

For OpenSSL, in the past, we actually had great problems not
to break the ABI just because of a security fix. We also had
to add new public functions to fix a security issue. We don't
want to add new features in old releases, but sometimes we're
forced to do it anyway.

All I'm saying is that in the case you offer long term support
for multiple versions, it might not be possible to follow the
semver version scheme, so we won't claim to follow it. It might
work for some projects, but it doesn't for us.

I also don't see how a distro forking it to add a new feature is
helpful at all. At some point they will want to use the new
upstream version anyway, and they'll just have the same problem
that semver doesn't work in that case.

Note that I'm not saying semver is not useful, I think more
projects should adapt it, it just doesn't work for all of them.

<!-- gh-comment-id:531477425 --> @kroeckx commented on GitHub (Sep 14, 2019): As Debian Developer, I perfectly know how distributions work. Since the Linux kernel started to have long term support for the kernels, Debian has picked one of those longterm kernels for the release. But even the kernel can't keep the ABI stable. Debian just had a stable release update that changed from: linux-image-4.19.0-5-amd64 4.19.37-5+deb10u2 to: linux-image-4.19.0-6-amd64 4.19.67-2 Notice the change from -5 to -6, because it's not compatible anymore. But the important part is that Debian switched to an upstream kernel that is supported upstream and no longer needs to maintain it's own fork of some random release. There is little point in having all distro's do the same work when you can just do it once upstream. For OpenSSL, in the past, we actually had great problems not to break the ABI just because of a security fix. We also had to add new public functions to fix a security issue. We don't want to add new features in old releases, but sometimes we're forced to do it anyway. All I'm saying is that in the case you offer long term support for multiple versions, it might not be possible to follow the semver version scheme, so we won't claim to follow it. It might work for some projects, but it doesn't for us. I also don't see how a distro forking it to add a new feature is helpful at all. At some point they will want to use the new upstream version anyway, and they'll just have the same problem that semver doesn't work in that case. Note that I'm not saying semver is not useful, I think more projects should adapt it, it just doesn't work for all of them.
Author
Owner

@wizzwizz4 commented on GitHub (Sep 14, 2019):

@kroeckx I can't see why you would ever need to add new public functions to fix a security vulnerability, unless said security vulnerability mandated actions to be taken by software developers, in which case you're making them update their version anyway.

<!-- gh-comment-id:531489228 --> @wizzwizz4 commented on GitHub (Sep 14, 2019): @kroeckx I can't see why you would ever need to add new public functions to fix a security vulnerability, unless said security vulnerability mandated actions to be taken by software developers, in which case you're making them update their version _anyway_.
Author
Owner

@klehelley commented on GitHub (Sep 16, 2019):

To rephrase the question to see if I understood it well, you are talking about a piece of software that, at a given time, has at least two incompatible versions that are in active development with the same level of support (so any kind of change can happen to any of these active versions, including breaking changes)? This becomes a hard problem to solve when using SemVer if the only thing one considers is the version string.

Strictly using SemVer, I do not see how one can make this work.

It is not just a matter of "just take the next available MAJOR number and use it", as it would mean conceptually having to maintain and document a graph of versions so that user can know which path to follow when upgrading. It is already complicated enough when not looking at the versioning string strategy. Trying to comply to SemVer while keeping the same product name makes things harder for everyone IMO.

Now thinking out of the box, one can use one of the following strategies (that are conceptually the same in the end):

  • Each active "branch/generation" has a different name. It does not need to be a completely original thing, so brand recognition does not have to be thrown out the window. One can have Product A, Product B and Product C -- or Product 1, Product 2 and Product 3... -- as the product name, and each of them uses the SemVer versioning strategy directly.
  • The versioning strategy does not directly use SemVer, as the version string in uses has a fourth member. The first number used is the "branch/generation" within which changes follow a logical progression and users are supposed to update following that path. When stripped of the first number, then the version string uses SemVer.

Do note that a lot of discussions have happened here regarding the second solution I list here. The reason these have been around for so long is not because it is a bad solution (I think it is the best way to go considering the constraints in place), but because some people consider that the SemVer spec should be updated to include that fourth number (in effect either forcing projects who do not care about that fourth number to use it, or making the specification more complex by adding yet another optional part).

<!-- gh-comment-id:531755735 --> @klehelley commented on GitHub (Sep 16, 2019): To rephrase the question to see if I understood it well, you are talking about a piece of software that, at a given time, has at least two incompatible versions that are in active development with the same level of support (so any kind of change can happen to any of these active versions, including breaking changes)? This becomes a hard problem to solve when using SemVer if the only thing one considers is the version string. Strictly using SemVer, I do not see how one can make this work. It is not just a matter of "just take the next available MAJOR number and use it", as it would mean conceptually having to maintain and document a graph of versions so that user can know which path to follow when upgrading. It is already complicated enough when not looking at the versioning string strategy. Trying to comply to SemVer while keeping the same product name makes things harder for everyone IMO. Now thinking out of the box, one can use one of the following strategies (that are conceptually the same in the end): * Each active "branch/generation" has a different name. It does not need to be a completely original thing, so brand recognition does not have to be thrown out the window. One can have Product A, Product B and Product C -- or Product 1, Product 2 and Product 3... -- as the product name, and each of them uses the SemVer versioning strategy directly. * The versioning strategy does not directly use SemVer, as the version string in uses has a fourth member. The first number used is the "branch/generation" within which changes follow a logical progression and users are supposed to update following that path. When stripped of the first number, then the version string uses SemVer. Do note that a lot of discussions have happened here regarding the second solution I list here. The reason these have been around for so long is not because it is a bad solution (I think it is the best way to go considering the constraints in place), but because some people consider that the SemVer spec should be updated to include that fourth number (in effect either forcing projects who do not care about that fourth number to use it, or making the specification more complex by adding yet another optional part).
Author
Owner

@claell commented on GitHub (Sep 16, 2019):

@ljharb

If you have a v1 line and a v2 line, and you need to add a breaking change to v1, what prevents making a v3 (v2, plus the fix) and those users having to upgrade to it?
(eg I'm not clear on what sort of breaking change bugfix would be "ok" for v1 users to accept, but the breaking changes in v2 would not be "ok" for them to also accept)

I guess v2 plus the fix won't simply work here, because v1 users use v1 probably mainly for stability concerns (or other reasons). Thus shipping a fixed v2 to them won't work, but they want a fixed v1 for them. I am not sure whether that really increases stability, so maybe the users are wrong with their behaviour. However that is how it is currently done and wanted.

Also this is only about MAJOR versions. If we talk about MINOR versions things might get even more complicated. Let's assume we have

  • v1.0.0
  • v1.1.0
  • v1.2.0

All of them being used in some distributions. Now there is a security problem that needs fixing by adding new features, thus the MINOR version number has to be increased. The problem here is that there is already a v1.1.0 and v1.2.0. So the fixed versions would then be v1.3.0, v1.4.0 and v1.5.0. How to tell the users of those version to which version they should upgrade?


@jeme

The only reason I can see for this is within commercial projects where you don't wan't to provide your customers that is paying for maintenance of version v1.x with all the features of v2.x which you sold to another customer just because the customer of v1.x has asked for a new feature.

I guess here the case is that the "customers" don't want to use the latest version, but want to stick with their version for a longer time. I guess SemVer is just not meant for such long term support software.


@klehelley

To rephrase the question to see if I understood it well, you are talking about a piece of software that, at a given time, has at least two incompatible versions that are in active development with the same level of support

One part of the question is about that (at least that is how I understand incompatible - it means incrementing the MAJOR version number, correct?).

The other part is about having one MAJOR version with several MINOR versions used at the same time (see the example above).

I have seen those issues about adding a fourth number. Thanks for bringing that idea up again. This might be a way to fix the issue, although I am not entirely sure whether it is a good solution for this case that probably has a variety of versions needing support.

<!-- gh-comment-id:531846982 --> @claell commented on GitHub (Sep 16, 2019): @ljharb > If you have a v1 line and a v2 line, and you need to add a breaking change to v1, what prevents making a v3 (v2, plus the fix) and those users having to upgrade to it? > (eg I'm not clear on what sort of breaking change bugfix would be "ok" for v1 users to accept, but the breaking changes in v2 would not be "ok" for them to also accept) I guess v2 plus the fix won't simply work here, because v1 users use v1 probably mainly for stability concerns (or other reasons). Thus shipping a fixed v2 to them won't work, but they want a fixed v1 for them. I am not sure whether that really increases stability, so maybe the users are wrong with their behaviour. However that is how it is currently done and wanted. Also this is only about MAJOR versions. If we talk about MINOR versions things might get even more complicated. Let's assume we have - v1.0.0 - v1.1.0 - v1.2.0 All of them being used in some distributions. Now there is a security problem that needs fixing by adding new features, thus the MINOR version number has to be increased. The problem here is that there is already a v1.1.0 and v1.2.0. So the fixed versions would then be v1.3.0, v1.4.0 and v1.5.0. How to tell the users of those version to which version they should upgrade? --- @jeme > The only reason I can see for this is within commercial projects where you don't wan't to provide your customers that is paying for maintenance of version v1.x with all the features of v2.x which you sold to another customer just because the customer of v1.x has asked for a new feature. I guess here the case is that the "customers" don't want to use the latest version, but want to stick with their version for a longer time. I guess SemVer is just not meant for such long term support software. --- @klehelley > To rephrase the question to see if I understood it well, you are talking about a piece of software that, at a given time, has at least two incompatible versions that are in active development with the same level of support One part of the question is about that (at least that is how I understand incompatible - it means incrementing the MAJOR version number, correct?). The other part is about having one MAJOR version with several MINOR versions used at the same time (see the example above). I have seen those issues about adding a fourth number. Thanks for bringing that idea up again. This might be a way to fix the issue, although I am not entirely sure whether it is a good solution for this case that probably has a variety of versions needing support.
Author
Owner

@ljharb commented on GitHub (Sep 16, 2019):

Semver is meant to convey breakage, not stability. If they’re on v1.1 and don't want v1.2+, then they also don’t want any new features ¯\_(ツ)_/¯ if a fix isn’t a patch, then they simply can’t get it unless they upgrade through the minor or major that contains it.

<!-- gh-comment-id:531848721 --> @ljharb commented on GitHub (Sep 16, 2019): Semver is meant to convey breakage, not stability. If they’re on v1.1 and don't want v1.2+, then they also don’t want any new features ¯\\\_(ツ)_/¯ if a fix isn’t a patch, then they simply can’t get it unless they upgrade through the minor or major that contains it.
Author
Owner

@claell commented on GitHub (Sep 16, 2019):

then they also don’t want any new features ¯_(ツ)_/¯

Exactly. I guess most of them only want a rock solid and reliable system :)

if a fix isn’t a patch, then they simply can’t get it unless they upgrade through the minor or major that contains it.

That is not working because they probably expect a very stable and secure system. So stopping the support of older releases isn't a solution at least in the current situation I guess.

<!-- gh-comment-id:531852210 --> @claell commented on GitHub (Sep 16, 2019): > then they also don’t want any new features ¯\_(ツ)_/¯ Exactly. I guess most of them only want a rock solid and reliable system :) > if a fix isn’t a patch, then they simply can’t get it unless they upgrade through the minor or major that contains it. That is not working because they probably expect a very stable and secure system. So stopping the support of older releases isn't a solution at least in the current situation I guess.
Author
Owner

@ljharb commented on GitHub (Sep 16, 2019):

I agree - i prefer to support all precious major and minor lines where possible - but it’s not a simple bugfix if it requires adding new things or breaking changes. The unfortunate reality for these customers is that “not upgrading” is the opposite of stable - the farther you are from the edge, the more it’ll cut you :-)

<!-- gh-comment-id:531858910 --> @ljharb commented on GitHub (Sep 16, 2019): I agree - i prefer to support all precious major and minor lines where possible - but it’s not a simple bugfix if it requires adding new things or breaking changes. The unfortunate reality for these customers is that “not upgrading” is the opposite of stable - the farther you are from the edge, the more it’ll cut you :-)
Author
Owner

@klehelley commented on GitHub (Sep 17, 2019):

I'm tempted to say that secure and stable are somewhat at odds, and even with a not too complicated, stable code base, it may happen that a security fix requires a breaking change.

In that case one strategy could be to add the more secure way to use the piece of software with additions with the old problematic parts deprecated (and that deprecation and its reason laid out in a clear, easy to find documentation), in which case it is only a MINOR upgrade.

That strategy is likely a good way to give the users time to adapt the way they use your piece of software. And if they choose not to change things on their side, they can still upgrade if they choose to (say there are PATCH changes they are interested in).

One thing to keep in mind is that for a project that is careful about minimizing regressions (not only bugs but performances, etc.) and uses SemVer, an upgrade of a dependency to that project from x.y.z to x.y+1.z should be no more risky than an upgrade from x.y.z to x.y.z+1.

<!-- gh-comment-id:532110917 --> @klehelley commented on GitHub (Sep 17, 2019): I'm tempted to say that secure and stable are somewhat at odds, and even with a not too complicated, stable code base, it may happen that a security fix requires a breaking change. In that case one strategy could be to add the more secure way to use the piece of software with additions with the old problematic parts deprecated (and that deprecation and its reason laid out in a clear, easy to find documentation), in which case it is only a MINOR upgrade. That strategy is likely a good way to give the users time to adapt the way they use your piece of software. And if they choose not to change things on their side, they can still upgrade if they choose to (say there are PATCH changes they are interested in). One thing to keep in mind is that for a project that is careful about minimizing regressions (not only bugs but performances, etc.) and uses SemVer, an upgrade of a dependency to that project from `x.y.z` to `x.y+1.z` should be no more risky than an upgrade from `x.y.z` to `x.y.z+1`.
Author
Owner

@jwdonahue commented on GitHub (Oct 6, 2019):

The only way to be fully SemVer compliant in the OP's scenario is to change the name of the product.

WizBangAPI.zero
SemVer version history

WizBangAPI.one
SemVer version history

WizBangAPI.two
SemVer version history

Otherwise, SemVer just doesn't apply. What it sounds like the OpenSSL folks are doing for versioning doesn't give me a warm fuzzy about their development practices or their product.

<!-- gh-comment-id:538709704 --> @jwdonahue commented on GitHub (Oct 6, 2019): The only way to be fully SemVer compliant in the OP's scenario is to change the name of the product. WizBangAPI.zero SemVer version history WizBangAPI.one SemVer version history WizBangAPI.two SemVer version history Otherwise, SemVer just doesn't apply. What it sounds like the OpenSSL folks are doing for versioning doesn't give me a warm fuzzy about their development practices or their product.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/semver#7366