Semantic Versioning (SemVer): MAJOR.MINOR.PATCH Explained
Semantic Versioning is the contract between library authors and consumers. Version numbers communicate intent: does upgrading break my code? This guide explains exactly when to increment each segment, how pre-release identifiers work, and how to automate versioning with Conventional Commits — so your changelogs write themselves.
Related Products
on GumroadDeveloper Productivity Bundle
Stop rebuilding the same setup every project. 51 VSCode snippets, 40 Git aliases, 5 Docker Compose stacks, 5 GitHub Actions workflows, 5 README templates, and a dotfiles kit. Set up a professional dev environment in under an hour.
Buy on Gumroad →AI Prompt Engineering Toolkit
58 structured prompt templates for Claude, ChatGPT, and Gemini — organized by use case. Code Review, Debugging, Documentation, Architecture, and 10 model-specific tips. Stop writing prompts from scratch.
Buy on Gumroad →Developer Cheat Sheet Bundle
10 print-ready cheat sheets for the tools developers use every day: Git, Docker, Linux CLI, SQL, Regex, HTTP Status codes, VS Code shortcuts, Bash scripting, jq/JSON, and Markdown.
Buy on Gumroad →You Might Also Need
JSON Formatter & Validator
Format, beautify, and validate JSON online. Paste your JSON to instantly pretty-print it with 2-space, 4-space, or tab indentation. Minify JSON too. Free, runs in your browser.
Open free tool →
Regex Tester
Free regex tester. Test regular expressions against multiple strings with expected match/no-match assertions — see instant pass/fail results. Built-in presets for email, URL, IPv4, and phone. Pro: unl
Open free tool →
Base64 Encoder & Decoder
Free Base64 Encoder & Decoder. Convert text, images, and any file to Base64 and back. Supports URL-safe Base64, image data URIs, and file download from Base64. Runs 100% in your browser — no data sent
Open free tool →
More Free Tools
Related Articles
curl 深度使用手冊:API 測試從入門到進階
curl 是每位開發者必備的 CLI 工具。本文涵蓋 GET/POST/PUT/DELETE 請求、認證、header 設定、檔案上傳、除錯技巧,以及 REST API 測試的完整實戰範例。
Best AI Code Review Tools 2026: CodeRabbit, Sourcery, DeepCode & Bito Compared
Compare top AI code review tools for 2026: CodeRabbit, Sourcery, DeepCode, and Bito. Features, pricing, GitHub/GitLab integration, and choosing the right tool for your team.
AI Code Review Tools 2026: GitHub Copilot, CodeRabbit, Qodo Merge Ranked
Compare AI code review tools for 2026: GitHub Copilot code review, CodeRabbit, Qodo Merge, Sourcery, and PR-Agent. Pricing, accuracy, and GitHub integration.
AI Coding Tools Comparison 2026: GitHub Copilot vs Cursor vs Windsurf vs Cline
Comprehensive comparison of the best AI coding tools in 2026: GitHub Copilot, Cursor, Windsurf, and Cline. Pricing, features, model support, and real-world benchmarks.
AI Pair Programming in 2026: GitHub Copilot vs Cursor vs Claude Code
Master AI pair programming in 2026. Compare GitHub Copilot, Cursor, and Claude Code for autocomplete, chat, and agentic workflows. Includes setup guides and productivity tips.
Enjoying this tool? Get more like it.
Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.
Unlock AI-Powered Dev Tools
- ⚡ AI Code Review, Doc Generator & SQL Builder
- ⚡ All premium templates & early access
- ⚡ Member discounts on Gumroad products
$9/mo after trial · Cancel anytime
Want the full toolkit?
Get DevPlaybook Pro
Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.
MIT licensed · Instant download · No subscription
See what's included → Browse all deals →SemVer Format & Decision Rules
Given a version number MAJOR.MINOR.PATCH, increment each part based on the nature of the change. Reset lower segments to zero when incrementing a higher one.
# PATCH: backward-compatible bug fix
# Before: 1.4.2 → After: 1.4.3
function getUserById(id: string): User | null {
// Fixed: was throwing instead of returning null for missing users
return db.users.find(u => u.id === id) ?? null;
}
# MINOR: new backward-compatible feature
# Before: 1.4.3 → After: 1.5.0
function getUserById(id: string, options?: { includeDeleted?: boolean }): User | null {
// New: optional includeDeleted parameter added
const query = options?.includeDeleted ? db.users : db.users.where({ deleted: false });
return query.find(u => u.id === id) ?? null;
}
# MAJOR: breaking change (changed return type)
# Before: 1.5.0 → After: 2.0.0
async function getUserById(id: string): Promise<User> {
// Breaking: now async, throws UserNotFoundError instead of returning null
const user = await db.users.findById(id);
if (!user) throw new UserNotFoundError(id);
return user;
} Pre-Release Versions & Build Metadata
Use pre-release identifiers for software that is not yet stable. Precedence order: alpha < beta < rc < release. Build metadata is ignored during version comparison.
# Pre-release version progression
1.0.0-alpha # early internal testing
1.0.0-alpha.1 # second alpha build
1.0.0-beta.1 # external testing begins
1.0.0-rc.1 # release candidate — feature freeze
1.0.0 # final release
# Precedence (lower to higher):
# 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta
# < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0
# Build metadata (IGNORED during comparison)
1.0.0+20241201.sha.abc1234 # date + git SHA
1.0.0+build.42 # CI build number
# 1.0.0+build.42 == 1.0.0+build.99 (same version, different builds) Conventional Commits → Version Bump Mapping
Conventional Commits encode the version bump type directly in the commit message. Tools like semantic-release and release-please read these to automate releases entirely.
# MAJOR bump — breaking change (two ways to signal)
feat!: change getUserById to async with error throwing
# OR footer notation:
fix: correct edge case in user lookup
BREAKING CHANGE: getUserById now throws UserNotFoundError instead of returning null
# MINOR bump — new feature
feat: add includeDeleted option to getUserById
feat(api): add batch user lookup endpoint
# PATCH bump — bug fix, performance, refactor
fix: prevent null pointer when user id is empty
perf: cache user lookup results for 5 minutes
refactor: extract user mapper to separate module
# No version bump (ignored by release tools)
docs: update getUserById JSDoc examples
test: add edge case tests for getUserById
chore: upgrade dev dependencies
ci: add caching to GitHub Actions workflow SemVer vs CalVer Comparison
| Dimension | SemVer (1.2.3) | CalVer (2024.03.15) |
|---|---|---|
| Signals | Breaking changes & new features | Release date & cadence |
| Best for | Libraries, APIs, packages | OSes, apps, tools with fixed schedules |
| Examples | React 18.2.0, Django 4.2.1 | Ubuntu 24.04, pip 24.0 |
| Automation | semantic-release, release-please | Date-based scripts |
| Ecosystem support | npm, PyPI, Cargo, RubyGems | Project-specific (no standard tooling) |
Changelog Generation Tools
- ✓semantic-release — Fully automated: reads commits, determines version, publishes to npm/GitHub, updates CHANGELOG.md. Zero configuration for projects following Conventional Commits. Best for libraries.
- ✓release-please (Google) — Creates a Release PR that accumulates all changes since the last release. You control when to merge. Supports multi-package monorepos. Best for apps and teams wanting a manual merge gate.
- ✓standard-version — Local CLI that bumps version, updates CHANGELOG.md, and creates a git tag. No CI integration required. Good for teams starting out.
- ✓git-cliff — Rust-based, highly customizable changelog generator. Supports custom templates (Tera syntax) and any commit format. Fast and configurable for non-standard commit styles.
Frequently Asked Questions
When should I increment MAJOR vs MINOR vs PATCH?▼
Increment PATCH (1.0.0 → 1.0.1) for backward-compatible bug fixes only — no new features, no API changes. Increment MINOR (1.0.0 → 1.1.0) when you add new functionality in a backward-compatible way — new functions, new optional parameters, new endpoints. Increment MAJOR (1.0.0 → 2.0.0) for any breaking change — removing a function, changing a function signature, changing the API response format, or dropping support for a language version.
What does 0.x.y versioning mean?▼
Versions below 1.0.0 are considered initial development. The API is considered unstable — anything may change at any time. In 0.x.y, the MINOR version behaves like MAJOR: breaking changes can happen on MINOR bumps. Once your public API is stable and ready for production use, release 1.0.0. Many libraries stay at 0.x for years; do not assume 0.x means abandoned or immature.
How do pre-release versions work in SemVer?▼
Append a hyphen and identifier: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-beta.2, 1.0.0-rc.1. Pre-release versions have lower precedence than the release: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-rc.1 < 1.0.0. Use alpha for early internal testing, beta for external testing with known issues, and rc (release candidate) for the version that will become the final release unless critical bugs appear.
What is build metadata and when is it used?▼
Build metadata is appended with a plus sign: 1.0.0+20241201, 1.0.0+sha.abc1234. It carries information about the specific build — date, git SHA, build number — but has NO effect on version precedence. Two versions with different build metadata are considered equal for dependency resolution purposes (1.0.0+build1 == 1.0.0+build2). It is primarily used for traceability in enterprise environments.
How does SemVer map to Conventional Commits?▼
Conventional Commits provides a machine-readable commit format that maps directly to SemVer increments. Commits with 'BREAKING CHANGE:' in the footer or '!' after the type (feat!:, fix!:) trigger a MAJOR bump. Commits starting with 'feat:' trigger a MINOR bump. Commits starting with 'fix:', 'perf:', 'refactor:', etc. trigger a PATCH bump. Tools like semantic-release and release-please read your git history and automatically determine and apply the correct version bump.
SemVer vs CalVer — which should I use?▼
SemVer (MAJOR.MINOR.PATCH) is best for libraries and APIs where communicating breaking changes to consumers is essential — it tells users exactly what kind of change to expect. CalVer (calendar versioning, e.g. 2024.1, 2024.03.15) is better for applications, OS distros, and tools where the release date is more meaningful than API stability (Ubuntu uses YY.MM). Use SemVer for any package published to npm, PyPI, or similar registries. Use CalVer for end-user software with predictable release schedules.