Semantic Versioning

Software is almost always versioned to coordinate installation, upgrades and correct interfacing with other software. While a flat linear numbering such as 123, 124, 125… might do the job, Semantic Versioning (SemVer) presents a better numbering scheme. It contains more useful information. Each part of the version number has a well-defined meaning. This helps software professionals and automation tools to more easily update software versions for their applications.

Traditionally, every software vendor designed their own numbering scheme, sometimes with semantics. From the late 1990s, software became more open sourced. As applications were increasingly built from many open source components, it became essential to know and use the correct version of each component. SemVer provides a common definition.

Without a proper versioning scheme, it becomes difficult to update software and its dependencies, leading to what's often called dependency hell.

Discussion

  • Could you describe the main parts of a semantic version number?
    Basic syntax of semantic versioning. Source: Rana 2019.
    Basic syntax of semantic versioning. Source: Rana 2019.

    A semantic version number has three core parts, written in the form of x.y.z, where x, y and z are numbers:

    • Major: Incremented when incompatible API changes are made. Applications and other software that use the affected APIs will break. Hence, their code have to be updated.
    • Minor: Incremented when new functionality is added in a backward compatible manner. It's safe to update to a new minor version without requiring code changes. Code changes are needed only to make use of the new features.
    • Patch: Incremented when backward compatible bug fixes are made. No new features are added. Some call this micro.

    As an example, consider the base version number 1.0.0. A bug fix to an internal implementation is a patch, resulting in 1.0.1. Suppose a new argument with default value is added to a public method, and the default value is consistent with the base version. This is a minor update, resulting in 1.1.0. If the new argument has no default value, this is an incompatible API change, resulting in 2.0.0.

  • Could you describe the SemVer parts about pre-release and build?
    Parts of a semantic version number. Source: Devopedia 2020.
    Parts of a semantic version number. Source: Devopedia 2020.

    Sometimes we wish to release software informally to some users for testing purposes. These are called pre-releases. In SemVer, this is specified by a hyphen followed by one or more dot-separated pre-release identifiers. Identifiers can include hyphen and alphanumeric characters. For example, in 1.2.4-alpha.1, -alpha.1 is a pre-release part that has two pre-release identifiers. In pre-release, software may not be stable and might not satisfy the compatibility requirements implied by the normal version 1.2.4.

    Sometimes we wish to record build metadata such as who made the build, build machine, time of build, or checksum. In SemVer, this is specified by a plus sign followed by one or more dot-separated build identifiers. Identifiers can include hyphen and alphanumeric characters. For example, in 1.0.0-beta+exp.sha.5114f85, +exp.sha.5114f85 is the build part that has three build identifiers. 1.0.0+20130313144700 is an example with build information but not a pre-release.

    Both pre-release and build parts are optional. Pre-release part comes before the build part.

  • What's the precedence of version numbers in SemVer?
    SemVer ranges specify allowed versions of each dependency. Source: Van de Moere 2013.
    SemVer ranges specify allowed versions of each dependency. Source: Van de Moere 2013.

    When upgrading from a lower to a higher version, it's important to define how version numbers should be compared. Comparison is left to right. Thus, 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1.

    Two versions that differ only by the build part, have the same precedence. A pre-release version has lower precedence than its normal version. Numeric identifiers always have lower precedence than non-numeric identifiers. Thus, 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.

    Precedence is used when updating project dependencies via SemVer ranges. For example, in NPM projects, dependency version can be specified as:

    • 1.0 or 1.0.x to allow all patches to 1.0; ~1.0.4 to allow patches to 1.0.4
    • 1 or 1.x to allow all patches and minor updates to 1; ^1.0.4 to allow patches and minor updates to 1.0.4
    • * or x to allow any update
  • What are the benefits of using semantic versioning?
    NPM uses SemVer to streamline package updates. Source: NPM Inc 2014.

    When an application uses and depends on many software packages, SemVer helps in using the most suitable versions of these packages. Suppose a Node.js application currently uses 2.0.0 of a certain package. Suppose more recent versions 2.1.0 and 3.0.0 are available. By specifying ^2.0.0 in the configuration file, NPM package manager will update the package to 2.1.0 but not 3.0.0 thereby preserving backward compatibility.

    By using semantic version ranges, such as ^2.0.0, <3.0.0 or ~2.2.1, the application benefits from package updates without any update to the configuration file.

    Package developers can use SemVer to keep track of how the package has evolved and manage its lifecycle. Semantic versioning helps them to know what releases are compatible with others. SemVer also avoids dependency hell, which can happen when different versions of the same package are used by other packages in the same application.

  • Which are some well-known projects or communities using semantic versioning?
    NuGet package versioning, associated tasks and branches. Source: Varga 2015.
    NuGet package versioning, associated tasks and branches. Source: Varga 2015.

    We note a few projects as examples. Node.js uses SemVer. Versioned dependencies are specified in a configuration file, such as bower.json (for Bower) or package.json (for NPM). NPM also has a useful SemVer calculator.

    Python uses SemVer but it allows for a more flexible use beyond the SemVer specification. For example, Python PEP 440 allows a date-based versioning scheme, such as 2012.4 or 2012.7. It allows for alpha, beta and release candidate versions, such as 1.3a2, 1.3b1, and 1.3rc4. Post-releases are allowed, such as 1.3post2 or 1.3rc4.post2. Development releases are allowed, such as 1.3dev2. Public version identifier is separated from local version identifier with a plus sign, such as 1.0+ubuntu.1.

    Composer, a PHP dependency manager, adopts SemVer. It includes stability constraints such as -dev or -stable.. Versioned dependencies are specified in file composer.json.

  • Could you mention some best practices when using semantic versioning?

    The version core is formed of digits 0-9 but must not contain leading zeros. Thus, 2.1.0 is fine but 2.01.0 is not. Version 0.x.y can be used during initial development with an unstable public API. This can start with 0.1.0. Once software enters production, it should start with 1.0.0.

    Sometimes we see a prefix v, such as in v2.1.3. This is often seen as tag names in version control systems. This is acceptable although the version number is just 2.1.3.

    Package owners/developers must attempt to avoid frequent incompatible changes. The cost of major upgrades is significant. It's important to evaluate the cost/benefit ratio before introducing incompatible changes. Some even recommend creating a new library/package name rather than making incompatible changes to an existing one.

    If an incompatible change goes into a minor version by mistake, release a new minor version to restore compatibility. The incompatible changes can go into the next major release. Avoid modifying an existing release.

    Deprecating a public API should happen in at least one minor release before that API is removed in a subsequent major release.

  • What are some criticisms of semantic versioning?

    While the specifications are clear, putting them into practice is more difficult. It's not always clear if something is a bug fix or a new feature. For example, there's no consensus about the next version number if a new warning is added to a package.

    There's no fully automated way of knowing if a change is compatible. Code reviews, golden files and automated tests can address this. For example, a Java API package has two types of users: consumers who use the API and providers who implement the API. An API change can be compatible for some users and incompatible for others. Spring Boot uses version numbers to indicate the extent of change. Adopting SemVer would lead to too many major releases.

    SemVer is rigid in the sense that a minor change that "breaks" for 1% of users will still be considered as a major change. This may be okay for robots but not for humans. Version number must give us a sense of how much of the code has changed. Ultimately, SemVer is not going to protect us completely from breaking changes. We should instead take some time and responsibly update dependencies.

Milestones

1979

Oracle releases version 2.3 of its SQL-based RDBMS. This is just an example to show that some form of semantics is part of version numbers even in the 1970s or possibly earlier. Subsequently, Oracle evolves this numbering to the form major.maintenance.applicationserver.component.platform.

1994
Linux kernel version numbering system. Source: Love 2010, fig. 1.2.

Linux kernel version 1.0.0 is released. Subsequently, this project adopts a numbering system of the form major.minor.revision.stable. In later years, major.minor together represent a major stable release. Revisions to this include bug fixes, new drivers and even features. The optional stable part indicates stable (even numbers) or development (odd numbers) releases. Sometimes major is incremented if minor "gets too large".

May
2010

OSGi Alliance publishes a whitepaper titled Semantic Versioning. This versioning scheme is targeted at Java packages. A version number has four parts in this form: major.minor.patch.qualifier. Examples of this are 0.9.0, 1.11.2.20100202-R32, and 2.0.0.beta-20100202-R32. We should note that this is not exactly same as the SemVer specifications that comes out in 2011.

Jun
2011

Tom Preston-Werner publishes on GitHub version 1.0.0-beta of Semantic Versioning Specification. Version 1.0.0 appears in September.

Jun
2013

Version 2.0.0 of Semantic Versioning Specification is published.

Nov
2015

Drupal 8.0.0 is released. Starting with this version, Drupal adopts semantic versioning. In earlier versions, for example, a contributed module of version 1.0.0 might refer to 8.x-1.0 or 7.x-1.0 depending on the Drupal core version. The project's info.yml file resolved the ambiguity. Adopting semantic versioning simplifies this. Drupal is a PHP-based CMS. It's first version was open sourced in 2001.

References

  1. Anthony, Sebastian. 2015. "Linux version dilemma: Linus Torvalds is “running out of fingers and toes”." Ars Technica, February 17. Accessed 2020-06-26.
  2. Ashkenas, Jeremy. 2015. "Why Semantic Versioning Isn't." GitHub Gist, February 20. Accessed 2020-06-26.
  3. Athaydes, Renato. 2018. "Stop versioning libraries." Google Sites, January 16. Accessed 2020-06-26.
  4. Bachina, Bhargav. 2019. "Understanding Semantic Versioning Specification." BB Thoughts & Tutorials, on Medium, May 17. Accessed 2020-06-26.
  5. Cannon, Brett. 2020. "Why I don't like SemVer anymore." Blog, Tall, Snarky Canadian, June 12. Accessed 2020-06-26.
  6. Coghlan, Nick, and Donald Stufft. 2013. "PEP 440 -- Version Identification and Dependency Specification." PSF, March 18. Updated 2014-08-22. Accessed 2020-06-26.
  7. Composer Docs. 2020. "Versions and constraints." v1.10.8, March 6. Accessed 2020-06-26.
  8. Drupal. 2015. "Drupal 8.0.0." Drupal, November 19. Updated 2018-03-12. Accessed 2020-06-27.
  9. Drupal Issues. 2012. "[policy, no patch] Switch to Semantic Versioning for Drupal contrib extensions (modules, themes, etc)." Drupal, June 1. Updated 2018-11-09. Accessed 2020-06-26.
  10. Kempka, Matthias. 2013. "Semantic Versioning for Eclipse Developers." Blog, EclipseSource, June 28. Accessed 2020-06-26.
  11. Love, Robert. 2010. "Linux Kernel Development." Third Edition, Addison-Wesley. Accessed 2020-06-26.
  12. Matic. 2016. "History of Drupal." Blog, Agiledrop, October 6. Accessed 2020-06-26.
  13. NPM Docs. 2020. "About semantic versioning." NPM. Accessed 2020-06-26.
  14. NPM Inc. 2014. "Semantic versioning and npm." NPM Inc, on YouTube, December 5. Accessed 2020-06-26.
  15. Oracle Docs. 2019. "About Oracle Database Release Numbers." Database Upgrade Guide, Release 12.2, December 4. Accessed 2020-06-27.
  16. OSGi Alliance. 2010. "Semantic Versioning." Technical Whitepaper, Revision 1.0, May 6. Accessed 2020-06-26.
  17. Raible, Matt. 2019. "Semantic Versioning Sucks! Long Live Semantic Versioning." Blog, Okta, December 16. Accessed 2020-06-26.
  18. Rana, Ashu. 2019. "Branching and Release Strategies." Xebia Engineering Blog, on Medium, December 3. Accessed 2020-06-26.
  19. SemVer. 2020. "Semantic Versioning 2.0.0." Accessed 2020-06-26.
  20. SemVer GitHub. 2020. "semver/semver." GitHub, June 24. Accessed 2020-06-26.
  21. The Linux Kernel Docs. 2020. "How the development process works." The Linux Kernel, 5.8.0-rc2. Accessed 2020-06-26.
  22. Van de Moere, Jurgen. 2013. "A simple guide to semantic versioning." June 6. Accessed 2020-06-26.
  23. Varga, Gusztáv. 2015. "#2 GitVersion to the rescue." Medium, October 30. Accessed 2020-06-26.
  24. Wikipedia. 2020. "Software versioning." Wikipedia, June 19. Accessed 2020-06-26.
  25. Wikipedia. 2020b. "Oracle Database." Wikipedia, June 23. Accessed 2020-06-26.

Further Reading

  1. SemVer. 2020. "Semantic Versioning 2.0.0." Accessed 2020-06-26.
  2. Bachina, Bhargav. 2019. "Understanding Semantic Versioning Specification." BB Thoughts & Tutorials, on Medium, May 17. Accessed 2020-06-26.
  3. Cannon, Brett. 2020. "Why I don't like SemVer anymore." Blog, Tall, Snarky Canadian, June 12. Accessed 2020-06-26.
  4. OSGi Alliance. 2010. "Semantic Versioning." Technical Whitepaper, Revision 1.0, May 6. Accessed 2020-06-26.
  5. Eberhardt, Colin. 2016. "Semantic Versioning is not enough." Blog, Scott Logic, December 15. Accessed 2020-06-26.

Article Stats

Author-wise Stats for Article Edits

Author
No. of Edits
No. of Chats
DevCoins
3
0
1188
1
3
17
1627
Words
4
Chats
4
Edits
0
Likes
1126
Hits

Cite As

Devopedia. 2020. "Semantic Versioning." Version 4, June 27. Accessed 2020-11-24. https://devopedia.org/semantic-versioning
Contributed by
2 authors


Last updated on
2020-06-27 16:42:18
  • Software Configuration Management
  • Version Control
  • Software Engineering
  • Software Compatibility
  • Dependency Hell
  • Application Lifecycle Management