Format
Commit Message Structure
[optional scope]: [optional body] [optional footer(s)]
Parts Explained
typeCategory of change (feat, fix, etc.)
scopeSection of codebase affected (optional)
descriptionShort summary in imperative mood
bodyDetailed explanation (optional, after blank line)
footerMetadata like BREAKING CHANGE or issue refs
Rules
Imperative mood"add feature" not "added feature"
Lowercase typefeat: not Feat:
No periodDescription does not end with "."
Blank lineSeparate body/footer from description
Types
Core Types (SemVer-relevant)
featNew feature (triggers MINOR version bump)
fixBug fix (triggers PATCH version bump)
Extended Types (Common Convention)
buildBuild system or external dependencies
choreMaintenance tasks (no src/test changes)
ciCI configuration and scripts
docsDocumentation only changes
perfPerformance improvement
refactorCode change that neither fixes nor adds
revertReverts a previous commit
styleFormatting, whitespace (not CSS styling)
testAdding or correcting tests
Scope
Scope Usage
feat(auth): add OAuth2 login flow fix(parser): handle empty input gracefully docs(readme): update installation steps refactor(api): extract validation middleware
Scope Guidelines
Module namefeat(auth):, fix(parser):
Layer namefeat(api):, fix(db):
Feature areafeat(search):, fix(checkout):
Dependencybuild(deps):, chore(npm):
Omit if broadUse no scope for cross-cutting changes
Breaking Changes
Marking Breaking Changes
feat!: remove deprecated login endpoint feat(api)!: change response format to JSON:API fix!: drop Node 14 support
Footer-Style Breaking Change
feat(api): change user endpoint response BREAKING CHANGE: response now returns array instead of object. Update client parsing.
Rules
! after type/scopeShorthand breaking change marker
BREAKING CHANGE:Footer token (always uppercase)
BREAKING-CHANGE:Also valid (hyphen form)
SemVer impactTriggers MAJOR version bump
Any typeBreaking changes can apply to any type
Examples
Simple Commits
feat: add email notifications fix: prevent race condition in checkout docs: correct typo in contributing guide style: format with prettier refactor: simplify error handling logic
With Scope
feat(blog): add comment threading fix(auth): refresh token before expiry test(api): add missing edge case coverage ci(github): add Node 20 to test matrix
With Body and Footer
fix(parser): handle nested quotes correctly Previously, nested quotes caused the parser to enter an infinite loop. This adds a depth counter to prevent unbounded recursion. Closes #234
Footer
Footer Tokens
BREAKING CHANGE:Describes breaking API change
Closes #123Auto-close issue on merge
Fixes #456Auto-close issue (fix reference)
Refs #789Reference issue without closing
Reviewed-by: nameReviewer attribution
Co-authored-by: nameCo-author attribution
Multiple Footers
feat(api)!: redesign authentication flow Migrate from session-based to JWT auth. BREAKING CHANGE: /auth endpoints changed Closes #101 Refs #98, #99
Tooling
Commit Linting
npm install -D @commitlint/cli \ @commitlint/config-conventional echo "module.exports = { extends: \ ['@commitlint/config-conventional'] }" \ > commitlint.config.js
Popular Tools
commitlintLint commit messages against convention
huskyGit hooks (run commitlint on commit)
commitizen (cz)Interactive commit message builder
standard-versionAuto changelog + version bump
semantic-releaseFully automated release pipeline
release-pleaseGoogle's release automation tool
Commitizen Setup
npm install -D commitizen \ cz-conventional-changelog npx commitizen init cz-conventional-changelog # Use: npx cz (or git cz with alias)
Common Patterns
Version Bump Mapping
fix:PATCH (1.0.0 → 1.0.1)
feat:MINOR (1.0.0 → 1.1.0)
BREAKING CHANGEMAJOR (1.0.0 → 2.0.0)
docs:, style:, etc.No version bump
Changelog Grouping
## [1.2.0] - 2026-03-27 ### Features - add email notifications (abc1234) ### Bug Fixes - prevent race condition (#123) (def5678)
Revert Format
revert: feat(blog): add comment threading This reverts commit abc1234def5678.