mirror of
https://github.com/semver/semver.git
synced 2026-03-22 14:10:15 -05:00
Four numbers #293
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @ygoe on GitHub (Aug 30, 2017).
I see that the spec is pretty clear about only allowing exactly three numbers, separated by a dot. Not one or two numbers and not more. I'm looking for a solution to automatically label commits that are after a version tag of the kind "v1.1" or "v2.4.3".
I've previously implemented that like following:
This obviously completely goes against SemVer because my newer commits will then be considered older. In-order, but all on the wrong side of the tagged version.
The cleanest solution would be to append the number of commits after the mentioned tag after another dot. Maybe with a "-something" to declare it as pre-release. But that could easily (and probably even should always) lead to a fourth number. (You never know when after the tag "v1.0" a tag "v1.0.1" will appear, so the third number should not be used for this.)
Now while the spec says that four numbers are invalid, it could easily be interpreted in a way that leads to a correct sort order with four numbers. At least Windows/.NET versions support this. I have the impression that SemVer is generally unable or unsuitable to handle automatically generated version numbers, but what do you think of this idea of the fourth number anyway?
@jwdonahue commented on GitHub (Nov 19, 2017):
Nothing in the spec prevents you from putting numeric digits in the prerelease and build metadata fields. Prerelease is probably the best place for your auto-increment field if you want it to sort appropriately. The spec clearly states that "...identifiers consisting of only digits are compared numerically...".
@FichteFoll commented on GitHub (Nov 19, 2017):
See also #200.
@ygoe commented on GitHub (Nov 26, 2017):
@jwdonahue I already describes that but it won't work. Consider these commits with their hash values from e. g. Git:
With my past scheme I'd generate the following version strings:
As you can see the versions with the "-" always come after the released version. SemVer would interpret them as pre-release though and sort them before the released version. That's not what it should express. My desired scheme would generate the following version strings:
SemVer would sort this properly if it would accept four digits.
@mearns commented on GitHub (Nov 27, 2017):
For what it's worth, the concept of being "N commits after commit X" is not guaranteed to be unambiguous, since you can have multiple child commits of a single parent commit.
@ygoe commented on GitHub (Nov 27, 2017):
True. I assume you only release with such automatically generated version numbers from a single defined branch.
@jwdonahue commented on GitHub (Nov 27, 2017):
What you're trying to do is post release versioning, and that won't work. Somebody's always going to come along and want to add yet another .n to the scheme. The way I've solved this problem in the past is to always bump the patch number for automatic check-in triggers/scripts and to only allow such automated tagging on developer/feature branches. Check-ins to master or maintenance branches require appropriate manual tagging dependent on the kinds of changes made (in the absence of adequate AI/automation to properly categorize changes). My preference for developer/feature branch names is to include the parent branch name (if any), major, minor and patch numbers, then reset the major and minor version tags to 0.0 (for that new branch) and proceed to bump the patch level. For feature branches, when you reach feature complete, manually tag the appropriate check-in Id with an appropriate M.m.p, then merge into master or a maintenance branch. Builds prefix output buckets (directories/packages) with branch names so test automation easily finds the latest version for the specified branch.
@DennisSmolek commented on GitHub (Jan 19, 2018):
Wouldn't your "upcoming" releases use the pre-release notation?
1.0.0[Release]1.0.11.0.1-1or1.0.1-rc11.0.1-2or1.0.1-rc21.0.1[Release]1.0.21.0.2-1or1.0.2-rc11.0.2[Release]@ygoe commented on GitHub (Jan 20, 2018):
@DennisSmolek The point is that you won't know in advance what exactly the X in "Start working on X" will be when it's finished. It may be 1.0.1, 1.1, or 2.0, and it may change, and change back. Some have concerns that patch-level versions need to be compatible with the one before, which sometimes isn't the case during development. That would require unneccesary version number increases. I'd just say dev versions (pre-releases) are not guaranteed to be compatible with anything and it's fine to assume increasing just the patch number until you're certain that it will be bigger (and remain so until a release).
BTW, calling development snapshots "RC" isn't always appropriate. Microsoft does that a lot and they're criticised for that each time. E. g. ASP.NET Core 1.0 RC1 was not very compatible with RC2.
@ygoe commented on GitHub (Jan 20, 2018):
@jeme If, after 1.1.0-pre, you decide to undo what justified the increment of the second number, you might as well have never done it. So if you consider pre-release history, you have 1.2 after 1.0.1. If you don't consider it, you should have 1.0.2.
@jwdonahue commented on GitHub (Jan 21, 2018):
The whole idea that you need to know in advance, what the version number of the next release will be, is simply absurd. You might in fact have a target in mind, but "the best laid plans..." as they say. Your future version intentions are not a factor in determining what a release version should be. They aren't even mentioned in the spec. Tagging every commit with a version number is silly, brittle, error-prone and outright stupid, don't do it. Version numbers should be generated at build/release time, preferably after a full suite of tests have been run.
It is a good practice to require commit comments that contain information about the type of changes included in the check-in. Are they intended to be bug fixes, non-breaking feature additions or breaking changes? These can be used when evaluating what version number to generate at build/release time. But even semantic commits aren't going to be perfect because they only indicate the developer's stated intentions, not what actually happened. Testing and pull-request reviews are still required, and those are not perfect either. Littering the repository history with meaningless tags is a pointless exercise.
Instead of versioning the inputs, version the outputs. Version strings should be constructed manually or automatically at build/release time, not before. In fact, it shouldn't happen until after a full test suite has been run to prove the version constraints have been met. Then you write your version artifacts, sign and package everything. Tagging/labelling the commit Id(s) from which the product packaging was constructed, is a nice-to-have feature, but not entirely necessary. A simple log or other kind of database providing the necessary mappings is one alternative.
Developer and feature branches should build only prerelease packaging. One very good practice here is to fork off of the master branch and use the last X.Y.Z version numbers in dev/feat branch builds plus a prerelease tag of the form "-Dev.N" where N is the sequential build number. Then append to that, a build meta tag that includes the branch name and commit Id from which the product was built.
There is no need for SemVer to add an additional numeric field. It would definitely be a breaking change if it did. But then, why stop at four? Why not five or some variable number of numeric fields as others have proposed here? None are likely to ever be accepted by the community.
If Nuget and other packaging tools will not adhere to SemVer, either don't use them or use a mapping from your SemVer version to their non-SemVer version. Tell your packaging providers you want full compliance with SemVer and lots of helpful tooling.
@ygoe commented on GitHub (Jan 21, 2018):
@jwdonahue To summarise your long comment: Don't predict the future but only derive dev version numbers from past releases.
That's not supported by SemVer because when you add "-dev.1" to your recent "1.0" you'll get something that SemVer considers before 1.0 which is not the case. Can you offer a solution to the problem you described?
@jwdonahue commented on GitHub (Jan 22, 2018):
As it should! If you want to pull a prerelease version you should do so explicitly. But then, precedence only matters in relation to available version on a specific feed, site or release share, do you always mix your dev branches outputs with your release branch outputs? On the release side, there's no reason why you can't bump the patch number once, so you have a series of 1.0.1-dev.buildNum. Ultimately you are going to release a version greater than or equal to that anyway. Some teams start by bumping the minor number, since most sprints are about adding new features anyway.
IMO, you have failed to present acceptable arguments that justify revving SemVer to 3.x.x for the addition of another digit. The current version supports 99.9% of all the conceivable dev-ops scenarios, including those you've mentioned here. The only scenarios I've seen that aren't covered, involve translating/mapping from SemVer to foreign schemes, and it doesn't make sense for the spec to attempt to cover those.
@jwdonahue commented on GitHub (Jan 22, 2018):
@jeme, There are many scenarios that could lead a particular branch down dead-end revision trails. Consider all -a.Experimental prereleases from the research teams. This is why I always argue for such branches appending their branch name to product package names, not just the version meta-data. For experimental purposes, this isn't too much of a blocker for some early adopters, but it may be too much for flight-testing periodic early releases of feature branches, where you want your less sophisticated dog-food volunteers to test your entire dev/build/release/delivery chain. Things can get really complicated when you have parallel development on a product that has hundreds or even thousands of features. I have sometimes wished for a version number server cluster to allow different build clusters to transactionally reserve version strings.
Keep in mind that all prerelease versions must be treated as unstable. 1.0.1-AnyPrerelease may in fact contain intentional breaking changes and still be SemVer compliant. If you want to convey semantic version information regarding your intent for a particular prerelease, you should embed a semver triple within the prerelease thread.
UberLib 1.0.0 // Last release from master branch
UberLib 1.0.1-0.1.0.Dev1+Hash // First planned flight of vNext.
UberLib 1.0.1-0.1.1.Dev1+Hash // Oops! Fix bug in last nights flight.
UberLib 1.0.1-1.0.0.Dev1+Hash // Second planned flight of vNext.
UberLib 1.1.0 // Release 1.0.0 with deprecation notices feature instrumentation.
UberLib 1.1.1-1.1.0.Dev1+Hash // Third planned flight of vNext.
UberLib 1.1.1-Alpha.2.0.0+Hash // Flight test to outside dog-fooders.
UberLib 1.1.1-Beta.2.0.1+Hash // Flight test to larger group of early adopters.
UberLib 1.1.1-RC1.2.0.2+Hash // Much wider prerelease roll-out.
UberLib 2.0.2 // RC1 accepted for release.
Notice that the 1.1.0 release in the middle of all the early vNext flight tests may not have had much if any of the feature code being worked on in the Dev1 branch. All of those changes may have come from a policy and instrumentation branch forked off of 1.0.0 specifically for the purpose of collecting data and providing deprecation notices to customers. Also notice that I moved the alpha containing fields from the end of the release tag up to the front of it, when I got to the Alpha, Beta and Release series. It's one method to workaround the Dev > Beta precedence problem.
Despite all of SemVer's weaknesses, it has always proven to be strong enough for me and the people I've worked with, to come up with workable solutions that weren't too overly complicated.
@FichteFoll commented on GitHub (Jan 22, 2018):
I'd like to point out again that the concept of "post-release versions" has been discussed at lenght in #200 already (and other referenced issues).
@ygoe commented on GitHub (Jan 23, 2018):
@jeme All branches need version numbers generated, not just master/release. You want to identify their builds, too. I'm talking about those.
Alright, I think I have found my solution by now. I'd just increment the third number and make pre-releases with that. And if SemVer requests my pre-releases to hold up to the same compatibility constraints as releases, then I guess I'm just violating that, and I don't care. That's a good enough solution for me. And a simple one. Thank you for all the feedback that led me to here.
As I'm the issue reporter and I have the power to close this, I'm just doing that. Any other discussion can be continued in the mentioned issue, where it probably fits in better.