Conventional Commits
Conventional Commits is a specification for git commit messages that makes history machine-readable and human-scannable. The format:
<type>(<optional scope>): <subject>
<optional body>
<optional footer(s)>
Example: fix(parser): handle captions with no timestamps
Why the format exists
A git log is the only complete history a project has, and free-form messages (“fixed stuff”, “wip”) make it write-only. With typed commits:
git log --onelinebecomes scannable — you can see at a glance which commits changed behavior vs. housekeeping.- Changelogs generate themselves — tooling groups
feat:andfix:commits into release notes. - Version bumps can be automated (semantic versioning):
fix:→ patch release,feat:→ minor,BREAKING CHANGE→ major. - Reviewers and future debuggers can filter: “show me every
fix:touching the parser this month.”
The types
The two the spec defines, plus the conventional extended set:
| Type | Means | Version signal |
|---|---|---|
feat | New capability visible to users of the code | minor |
fix | Corrects wrong behavior | patch |
docs | Documentation only | — |
refactor | Restructures code, behavior identical | — |
test | Adds or fixes tests only | — |
chore | Maintenance that touches no production code behavior: dependency bumps, config, tooling, cleanup | — |
build / ci | Build system / CI pipeline changes | — |
perf | Performance improvement (behavior same, faster) | patch |
style | Formatting, whitespace — no logic change | — |
chore vs fix vs refactor — the common confusion: if user-visible
behavior was wrong and now is right → fix. If behavior is unchanged but the
code is structured differently → refactor. If no production code changed at
all (deps, configs, housekeeping) → chore.
Subject-line rules
- Imperative mood: “add retry logic”, not “added” or “adds” — read it as “if applied, this commit will add retry logic”.
- Keep it ≈50 characters (hard ceiling ~72); no trailing period.
- The scope in parentheses names the area touched:
feat(auth):,chore(deps):. Optional; use it when the repo is big enough to need it.
Body and footers
- The body explains why, not what — the diff already shows what.
BREAKING CHANGE: <description>in the footer (or!after the type:feat!:) marks a compatibility break → major version bump.- Footers carry structured trailers:
Fixes #42,Co-Authored-By: ....
Good and bad, side by side
BAD: update stuff
BAD: Fixed the bug where it crashed sometimes.
GOOD: fix(fetch): handle videos with no caption tracks
BAD: changes to README and also retry logic and tests
GOOD: feat(client): retry failed requests with backoff
(separate commit) docs: document retry behavior
One logical change per commit — if the subject needs “and”, split it.
Ecosystem
The spec: conventionalcommits.org. Enforcement/automation tooling:
commitlint (lints messages in CI or a git hook), semantic-release /
release-please (automate versioned releases from the commit stream).