Semantic versioning (SemVer) and version numbers
In short: SemVer numbers versions as MAJOR.MINOR.PATCH: major for incompatible changes, minor for new compatible features, patch for bug corrections.
In more detail: A version number should set expectations: can I update safely? Semantic Versioning 2.0 (semver.org) gives clear rules for that.
In Depth
The scheme
MAJOR.MINOR.PATCH, e.g. 2.4.1:
- PATCH (
2.4.1 → 2.4.2): backwards-compatible corrections. - MINOR (
2.4.2 → 2.5.0): new features, backwards compatible; patch back to 0. - MAJOR (
2.5.0 → 3.0.0): incompatible changes (breaking changes); minor/patch back to 0. Pre-releases:3.0.0-beta.1,-rc.2; build metadata:1.0.0+20260101.0.y.zcounts as unstable: anything may break. The first stable version is1.0.0.
Version ranges (npm, Python & co.)
^1.4.2(npm): compatible, allows1.x.xfrom 1.4.2 (not 2.0.0).~1.4.2: patch updates only (1.4.x).1.4.2: exact.>=1.2 <2: range.- Python:
~=1.4.2(compatible),==,>=. Plus lockfiles so builds stay reproducible.npm outdated,npm update, Renovate/Dependabot keep dependencies current; read major updates (changelog/migration guide) and test them calmly.
When is it a breaking change?
Removed/renamed functions or parameters, changed return values, different errors/exceptions, stricter validation, changed defaults, higher minimum versions (Node, Python), dropped platforms, changed API response formats, database schema changes. Everything users can rely on is part of the public interface. Better to deprecate first (warning, transition period), then remove in the next major.
Alternatives and practice
- CalVer (
2026.10, Ubuntu24.04): time-based, suits applications/releases on a rhythm. - Build/commit hashes for deployments.
- Conventional Commits (
feat:,fix:,feat!:) enable automatic version assignment and changelogs (semantic-release, release-please). - Git tags
v1.2.3, release notes with migration hints. - For web APIs: version in URL/header (see API versioning); apps show the version in the “About” dialog (support!).
- Stay consistent: better use a simple scheme reliably than a complicated one that often breaks.
See also: Git tags, releases and changelog, API versioning