In the world of software development, there is a scary place called "dependency hell." The larger your system, the greater the chance that one day you will fall into this trap.
In a system with a lot of dependencies, the release of new packages can quickly turn into a nightmare. If the dependencies are too strong, you cannot upgrade the package without upgrading the versions of all dependent packages. If the dependencies are too loose, you will have problems with licentious versions. “Hell of dependencies” is when too strong, or vice versa, too loose dependencies prevent you from developing your project easily and safely.
As a solution to this problem, I propose a simple set of rules that dictate how to assign and increment version numbers. In order for the system to work, for a start, you need to declare an open API. It should be a simple and clear document. Consider the version number in the format XYZ (Major.Minor.Patch).
When correcting errors that do not affect the API, the Patch version is increased. When adding or changing an API while maintaining backward compatibility, the Minor version increases. If the API is modified without preserving backward compatibility, then the Major version is incremented.
I call this system "Semantic Version Control." According to this scheme, the version numbers and how they change carry the meaning of the main code and how it changed from version to version.
')
Semantic Versioning Specification
The keywords "MUST (MUST)", "MUST NOT (MUST NOT)", "SHOULD (SHOULD)", "NOT SHOULD (SHOULD NOT)", "CAN (MAY)", in this document should be interpreted in accordance with the RFC 2119.
- A software product using Semantic Version Management MUST have an open API. This API must be declared within the code or in the application documentation. The API must be accurate and complete.
- The version number MUST consist of XYZ, where X, Y, and Z are positive numbers. X is the Major version, Y is the Minor version and Z is the Patch version. Each element MUST increase in increments of one. For example: 1.9.0 -> 1.10.0 -> 1.11.0.
- When the Major version increases, the Minor and Patch versions MUST be reset. When the Minor version is increased, the Patch version should be reset. For example: 1.1.3 -> 2.0.0 and 2.1.7 -> 2.2.0.
- After the version of the package is released, there should NOT be any changes to this package. All changes MUST be released with the new version.
- At the beginning of development, Major version is zero (0.yz). During this period, anything can change at any time. An open API MUST NOT be considered stable.
- Version 1.0.0 defines an open API. How the version number changes depends on this open API.
- Patch version Z (xyZ | x> 0) MUST be increased only if bug fixes are backward compatible with previous versions. Error correction eliminates incorrect behavior.
- Minor version Y (xYz | x> 0) MUST be increased if corrections are made that are compatible with previous versions. Minor version MUST be increased if any API element is marked as “Outdated”. Minor version CAN be increased if there are significant new features or improvements. Minor version MAY include changes to patch version. Patch version should be reset when the Minor version changes.
- Major version X (Xyz | X> 0) MUST be increased if corrections are made that are incompatible with previous versions. Major version MAY include changes to Minor and Patch versions. Patch and Minor versions should be reset when the Major version changes.
- Preliminary versions MAY be indicated by a dash and an identifier, separated by dots, immediately after the Patch version. The identifier MUST contain the characters [0-9A-Za-z-]. The preliminary version has lower priority than the same normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92.
- An assembly version MAY be indicated by a plus sign and an identifier, separated by dots, immediately after the Patch version or the preliminary version. The identifier MUST contain the characters [0-9A-Za-z-]. The build version has a higher priority than the same normal version.
Examples: 1.0.0 + build.1, 1.3.7 + build.11.e0f985a. - Priority MUST be calculated by splitting into Major, Minor, Patch, preliminary and assembly versions. Major, Minor and Patch versions always contain numbers. Preliminary and build versions MUST be sorted by comparing each identifier separated by a dot as follows: Identifiers containing only numbers are compared numerically and containing letters in the order specified
in ASCII. Numeric identifiers always take precedence over alphabetic characters. Examples: 1.0.0-alpha <1.0.0-alpha.1 <1.0.0-beta.2 <1.0.0-beta.11 <1.0.0-rc.1 <1.0.0-rc.1 + build. 1 <1.0.0 <1.0.0 + 0.3.7 <1.3.7 + build <1.3.7 + build.2.b8f12d7 <1.3.7 + build.11.e0f985a.
Why use Semantic Versioning?
This is not a new or revolutionary idea. In fact, you probably already did something similar. The problem is that “like” is not good enough. Without some kind of formal specification, version numbers are essentially useless for dependency management. By giving clear and reasonably flexible definitions,
you facilitate user interaction with your product.
A simple example that will show how Semantic Version Control will help you to avoid dependency hell. Consider a library called "Firetruck". It depends on the package called "Ladder". When Firetruck was created, the version of Ladder was 3.1.0. Since Firetruck uses various methods that were introduced in 3.1.0, you can safely update Ladder to versions greater than 3.1.0 but less than 4.0.0. Now that versions 3.1.1 and 3.2.0 of the Ladder package become available, you can upgrade to them and be aware that they will be compatible with existing software.
As a responsible developer, you will of course want to check package compatibility. Reality can be cruel, we can do nothing with it. What we can do is allow Semantic Version Management to provide you with an easy way to update packages. It will save your time and nerves.
If you like the idea of ​​Semantic Version Management, you just need to follow the rules outlined here. You can place a link to this documentation in the README file of your project, so that your colleagues, as well as people using your product, also follow Semantic version control.
FAQ
How should I change the version number at the initial stage 0.yz?
The easiest way is to start with version 0.1.0 and then increase the version number for each subsequent release.
How do I know if it's time to upgrade to version 1.0.0?
If your product has begun to be used by end users, it should be version 1.0.0. If you have a stable open API, you should upgrade to 1.0.0. If you are worried about backward compatibility, you should upgrade to 1.0.0.
Doesn't this impede rapid development and fast iteration?
Zero Major version, that's all you need. If your open API changes every day, you should be in version 0.xx or work on the next Major version.
If even the smallest changes do not have backward compatibility, will not I soon in version 42.0.0?
This is a matter of responsible development and foresight. Incompatible changes should not be made in small chunks in code that has many dependencies. The cost of updating may be too significant.
API documentation is too much work!
It is your responsibility as a professional developer creating a product intended for use by other people. Software management is a complex and extremely important part of maintaining project effectiveness.
What should I do if I accidentally indicated the Minor version instead of Major?
Once you understand that you have broken Semantic Version Control, you should fix the problem and release a new version that fixes the problems and restores backward compatibility.
What should I do if I update my internal dependency without changing the open API?
This is valid, if not how it does not affect the open API. A product that clearly depends on your package should have its own dependency specification and the author will notice a conflict.
How do I mark outdated functionality?
Outdated functionality, this is normal and you often have to resort to it in order to move forward. When you mark as outdated part of your open API, you have to do two things: (1) update the documentation, (2) release at least one release that supports both new and outdated functionality, so that users can smoothly restructure.
about the author
Posted by Semantic Version Control
Tom Preston-Werner , creator of Gravatars and co-founder of GitHub.
In order to express your questions and suggestions
create a question on GitHub .
This translation is on
githubLicense
Creative Commons - CC BY 3.0
http://creativecommons.org/licenses/by/3.0/