# Semantic Versioning

## Summary


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?

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?

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?

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?

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?

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 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.