The Conventional Commits standard
Conventional Commits (conventionalcommits.org) defines a format for commit messages:
<type>(<scope>): <subject>, optionally followed by a body
and a footer. It's the most adopted convention in open source and large companies for
automating versioning and changelogs.
The subject line
Max 50-72 characters, imperative present: "add" instead of "added" or "adds". No trailing period. Lowercase first letter. Mnemonic: if your message completes "If applied, this commit will...", the imperative verb fits: "if applied, this commit will add login flow".
Types and when to use them
- feat: new user-facing functionality.
- fix: bug fix.
- docs: documentation only.
- style: formatting (whitespace, semicolons); no behavior change.
- refactor: internal change without new feature or fix.
- perf: performance improvement.
- test: add or fix tests.
- build: changes to build system or dependencies.
- ci: CI pipeline changes.
- chore: auxiliary tasks not in the above.
- revert: revert a previous commit.
Scope: optional but useful
Scope identifies the affected area. feat(auth) reads better than
feat alone. Common conventions: module name (auth,
billing), package name in monorepos, or UI component (button,
nav).
Breaking changes
Two ways to mark a breaking change. Short: feat(api)!: rename user endpoints.
Explicit: add a BREAKING CHANGE: the /users/me route is now /me footer.
Versioning tools trigger a major bump on either.
Body and footer
The body explains the "why" when the subject isn't enough. Separate with a blank line.
Footers go last: Closes #123, Co-authored-by: Name
<email>, Refs: JIRA-456. Consumable by bots and automation.
Concrete benefits
With conventional commits, tools like standard-version or
semantic-release automatically generate: a Markdown changelog, a version
tag, a GitHub release. No more "someone has to write the changelog".
How to enforce
Hooks with commitlint + Husky validate every commit. PR templates remind the
format. In large projects, configuring the rule in CI prevents merging non-conforming
commits. Squash merges can rewrite the message on combination.