Conventional commits cheat sheet (with real examples)

Conventional commits is a small format that makes Git history readable, enables automated changelog tools, and signals to senior engineers that you know what you're doing. Bookmark this page, you'll come back to it.

The format in one line

<type>(<optional scope>): <short description>

[optional body]

[optional footer]

Examples:

feat: add password reset flow
fix(auth): use env secret instead of hardcoded JWT key
chore(deps): upgrade React to 18.3
docs: clarify env var setup in README
refactor(api): extract user-fetching into a helper
test: add coverage for null-email case

That's the whole format. The next section is the cheat sheet of types.

The complete type reference

TypeUse when…Example
featYou added a new user-facing featurefeat: add CSV export to dashboard
fixYou fixed a bugfix: prevent crash when user has no avatar
choreMaintenance, dependency upgrades, tooling, repo housekeepingchore: upgrade ESLint to 9.0
docsDocumentation only, README, comments, JSDocdocs: add API rate-limit table
refactorRestructuring code without changing behaviorrefactor: extract retry logic into helper
testAdding or changing tests onlytest: cover edge cases in date parser
perfPerformance improvements with no behavior changeperf: cache user lookups for 5 minutes
buildBuild system, package config, bundlerbuild: switch from webpack to vite
ciCI/CD config, GitHub Actions, GitLab CI, etc.ci: run tests on Node 20 and 22
styleFormatting only, whitespace, semicolons, prettierstyle: run prettier on src/
revertReverting a previous commitrevert: feat: add CSV export

The hard part: choosing between feat, fix, chore, and refactor

Most beginners get tangled here. The decision tree:

Examples of the same change with different correct types:

The optional scope

Scope tells reviewers where the change happened. It's optional but useful in larger codebases:

feat(auth): add password reset flow
fix(api): return 400 instead of 500 on null email
chore(deps): upgrade React to 18.3
docs(readme): document env var setup

Common scopes: auth, api, ui, db, deps, the name of a specific module. Whatever your team uses. Don't invent new scopes, match what's in the repo's history.

Breaking changes

If your change breaks backward compatibility, mark it with ! after the type:

feat!: rename `userId` to `user_id` in API responses

BREAKING CHANGE: All API consumers must update field name.

The ! tells everyone "this will require coordinating with consumers." The BREAKING CHANGE: footer gives details. Don't sneak breaking changes into fix or refactor commits, your downstream consumers will hate you.

The body (when to add one)

Most commits don't need a body. Add one when:

fix: cache user lookups for 5 minutes

We were making a DB query on every request, which was fine
at 10 req/s but starting to show in p99 latency at 200 req/s.

Five minutes was chosen because user role changes are rare
and the existing /users PATCH already invalidates the cache.

Closes IQ-142.

Real-world commit examples (good vs. bad)

Bad commits, and why

Good commits, and why

Why bother with all this

Three concrete reasons, in order of how much you'll feel them:

  1. Senior engineers will respect you instantly. A clean commit history signals that you understand professional norms. It's a 30-second cost that pays back forever.
  2. Automated tools work. Tools like standard-version, semantic-release, and changesets read your commits to auto-generate changelogs and bump versions. You don't have to write release notes, they write themselves.
  3. Future-you can debug faster. Six months from now, you'll git log --grep="auth" looking for when a bug was introduced. With conventional commits, you find it in 10 seconds. Without, you read a thousand lines of "updates" and "wip" and want to quit.

The two-line rule

  1. Subject line under 72 characters, lowercase, no period.
  2. If you need a body, leave one blank line, then write it. Wrap at 72 characters.

That's it. You now know more about commit messages than most third-year engineers.

Practice writing real commits

InternQuest gives you 150+ real engineering tickets where you fix a bug, write a conventional commit message, and open a PR, same flow as a professional team. Free.

Start your first mission →