/glossary/semver/semantic-versioning
What is semantic versioning (SemVer)?
- tool
- SemVer
- versions
- SemVer 2.0.0
- os
- any
Semantic versioning (SemVer) is a convention for version numbers of the form MAJOR.MINOR.PATCH, such as 2.4.1. Increment MAJOR for changes that break the public API, MINOR for new features that stay backward compatible, and PATCH for backward compatible bug fixes. Package managers rely on it: a range like ^2.4.1 accepts any later 2.x release because those must not break code written for 2.4.1.
The rules in practice
The semver package (the implementation npm uses) shows how versions are incremented and ordered:
npm init -y >/dev/null
npm install --silent --no-audit --no-fund semver@7 >/dev/null 2>&1
cat > rules.js <<'EOF'
const semver = require("semver");
console.log("patch:", semver.inc("2.4.1", "patch"));
console.log("minor:", semver.inc("2.4.1", "minor"));
console.log("major:", semver.inc("2.4.1", "major"));
console.log("pre: ", semver.inc("2.4.1", "premajor", "rc"));
const list = ["1.0.0", "1.0.0-rc.1", "1.0.0-alpha", "1.0.0-alpha.10", "1.0.0-alpha.2", "0.9.12", "1.0.0+build.5"];
console.log("sorted:", semver.sort(list).join(" "));
console.log("valid 1.2:", semver.valid("1.2"), "| valid v1.2.3:", semver.valid("v1.2.3"));
EOF
node rules.jsOutput
patch: 2.4.2 minor: 2.5.0 major: 3.0.0 pre: 3.0.0-rc.0 sorted: 0.9.12 1.0.0-alpha 1.0.0-alpha.2 1.0.0-alpha.10 1.0.0-rc.1 1.0.0 1.0.0+build.5 valid 1.2: null | valid v1.2.3: 1.2.3
Parts of a version
| Part | Example | Rule |
|---|---|---|
| MAJOR | 2.x.x | Incompatible API change; resets MINOR and PATCH to 0 |
| MINOR | x.4.x | New backward compatible functionality; resets PATCH to 0 |
| PATCH | x.x.1 | Backward compatible bug fix |
| Pre-release | 1.0.0-rc.1 | After a hyphen; sorts before the release 1.0.0 |
| Build metadata | 1.0.0+build.5 | After a plus; ignored when comparing precedence |
Pre-release identifiers are compared piece by piece: numeric parts numerically (alpha.2 < alpha.10), text parts alphabetically (alpha < rc).
Which number to bump
The public API is whatever you document as such: functions, command-line flags, configuration keys, HTTP endpoints, file formats. SemVer only works if you write it down, because "breaking" is measured against it.
| Change | Bump | Why |
|---|---|---|
| Remove or rename a public function, flag or option | MAJOR | Existing callers stop working |
| Change a default or a return type in an incompatible way | MAJOR | Same call, different result |
| Drop support for a runtime version (for example an old Node.js) | MAJOR (usual practice) | Users on that runtime can no longer upgrade |
| Add a new function or an optional parameter | MINOR | Old code keeps working, new code can use it |
| Mark something as deprecated | MINOR | Behaviour is unchanged, only a warning is added |
| Fix a bug without changing the documented behaviour | PATCH | Code that relied on the documented behaviour is unaffected |
| Change documentation, tests or internal refactoring only | PATCH or none | Nothing observable changes |
Once a version is published, its contents must not change: any fix, however small, is a new version.
Version 0.y.z
Major version zero is for initial development: anything may change at any time, and the public API is not considered stable. Many tools treat ^0.4.1 as >=0.4.1 <0.5.0 for that reason. Release 1.0.0 once other people depend on the API.
FAQ
Is v1.2.3 a semantic version?
Strictly, no: the spec defines the version as 1.2.3, and the semver.org FAQ calls the v prefix a common convention for tags. Tools like node-semver strip it (valid('v1.2.3') returns 1.2.3).
What if I released a breaking change as a minor version by mistake?
Do not change the published release. Publish a new minor that restores compatibility, then ship the breaking change in the next major; the semver.org FAQ gives the same advice.
How should I deprecate something under SemVer?
Mark it deprecated in a minor release, with documentation telling users what to use instead, and remove it only in a later major release.