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 →