Commit Smarter - Master Conventional Commits in Simple Steps
|

Conventional Commits: The Complete Guide with Cheatsheet

Reading Time: 4 minutes

I’ve read the full article. Here’s a complete rewrite with the cheatsheet table, restructured H2s, updated meta, and internal links woven in naturally.

Are your commit messages still "fix stuff""update", or "final FINAL v3"? You’re losing something real — readable history, automated changelogs, and a team that can debug without you.

Commit Smarter - Master Conventional Commits in Simple Steps

Conventional Commits is a one-page specification that fixes all of this. This guide covers everything: the format, every type, a ready-to-paste cheatsheet, and how to enforce it automatically in your repo.

Part of the Git series on this blog.
If you’re new to Git, start with Git Explained Simply before continuing. Already comfortable? The companion post Committing with Intention digs into the art of a good commit — pair it with this spec guide.


What Are Conventional Commits?

Conventional Commits is a lightweight convention on top of commit messages. It gives every commit a machine-readable type, an optional scope, and a human-readable description — all in one line.

Basic structure:

<type>[optional scope]: <description>

[Optional body]
[optional footer(s)]

Example:

feat(auth): add OAuth2 login via Google

Replaces the legacy username/password-only flow.
Closes #88

That single line tells your CI pipeline, your changelog generator, and your future self exactly what happened and why.


Conventional Commits Cheatsheet (All Types at a Glance)

Copy this into your team wiki or pin it to your Notion.

TypeWhen to UseVersion BumpExample
featA new feature for the userminorfeat(cart): add coupon code support
fixA bug fix for the userpatchfix(api): handle null response from payment
docsDocumentation changes onlynonedocs: update README with setup steps
styleFormatting, whitespace, semicolons (no logic)nonestyle: reformat auth module
refactorCode restructure — no new feature, no bug fixnonerefactor(db): extract query builder helper
perfPerformance improvementpatchperf(img): switch to WebP for thumbnails
testAdding or fixing testsnonetest(auth): add edge cases for token expiry
buildBuild system or external dependency changesnonebuild: upgrade webpack to v5
ciCI/CD config changesnoneci: add lint step to GitHub Actions
choreMaintenance that doesn’t fit anywhere elsenonechore(deps): update Node.js to v22
revertReverts a previous commitpatchrevert: feat(auth): add OAuth2 login

Breaking change? Add ! after the type or BREAKING CHANGE: in the footer.
feat(api)!: remove deprecated v1 endpoints → triggers a major version bump.


The Three Parts of a Conventional Commit

1. The Header (Required)

The header is the only required line. It follows:

<type>[(scope)]: <description>
  • type — from the cheatsheet above
  • scope — optional, in parentheses, names the module/area (authuiapi)
  • description — present-tense, lowercase, no period at the end
# Good
feat(checkout): add Apple Pay support

# Bad — past tense, vague, no type
Added some payment stuff

2. The Body (Optional, Recommended for Non-Trivial Changes)

Use the body to explain why, not what — the diff already shows what changed.

fix(token): use UTC for all expiry comparisons

Token validation was failing for users in UTC+5:30 because the
server was comparing local time. Standardising on UTC fixes this.

Leave a blank line between the header and body.

3. The Footer (Optional)

Use footers for two things: referencing issues and declaring breaking changes.

feat(api)!: replace REST endpoints with GraphQL

BREAKING CHANGE: All /v1/ REST routes have been removed.
Migrate to the GraphQL endpoint at /graphql.
Refs: #201
Closes #198

Fixes #N and Closes #N will automatically close the GitHub issue when the PR is merged.

For even richer commit metadata, see Git Trailers: The Commit Metadata Most Developers Skip — a natural extension of conventional footers.


How Conventional Commits Power Automation

This is where the format earns its keep. Each type maps to a semantic versioning action:

feat      →  minor bump   (1.2.0  →  1.3.0)
fix/perf  →  patch bump   (1.2.0  →  1.2.1)
BREAKING  →  major bump   (1.2.0  →  2.0.0)
docs/chore/ci/style → no bump

Tools that plug into this automatically:

  • semantic-release — reads your commits, bumps the version, generates a CHANGELOG.md, and publishes — zero manual input
  • conventional-changelog — generates changelogs from your history
  • release-please (by Google) — creates release PRs automatically on GitHub

How to Enforce Conventional Commits in Your Repo

You don’t want this to be voluntary. Automate the gate.

commitlint + Husky (Recommended)

npm install --save-dev @commitlint/cli @commitlint/config-conventional husky

commitlint.config.js:

module.exports = { extends: ['@commitlint/config-conventional'] };

Set up the commit-msg hook:

npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'

Now every commit message is validated before it lands. Bad format = blocked commit.

Commitizen (Interactive CLI)

If your team finds the format hard to remember, Commitizen gives them a guided prompt:

npm install -g commitizen
npx commitizen init cz-conventional-changelog --save-dev

Then run git cz instead of git commit.

VS Code Extension

Conventional Commits adds a guided commit UI directly in the editor sidebar. Good for onboarding juniors.


Conventional Commits vs Semantic Versioning — What’s the Difference?

They’re not the same thing, but they’re designed to work together.

Conventional CommitsSemantic Versioning (SemVer)
What it isA format for commit messagesA format for version numbers
ScopeYour git historyYour package/release tags
Who reads itHumans + toolingHumans + dependency managers
Examplefeat: add search1.4.0

Conventional Commits is the input. SemVer is the output. Tools like semantic-release do the translation automatically.


Linking Commits to Issues and Jira Tickets

Conventional Commits plays nicely with project tracking:

GitHub Issues:

fix(login): handle expired session redirect

Fixes #312

Jira:

feat(dashboard): add export to CSV

Refs: PROJ-456

The Fixes keyword closes the issue automatically on merge. Refs just links without closing.


Practical Examples (Copy & Paste)

# New feature with scope
feat(payments): integrate Razorpay checkout

# Bug fix
fix(auth): prevent redirect loop on token expiry

# Breaking change
feat(api)!: remove XML response format — JSON only

# Dependency update
chore(deps): bump lodash from 4.17.20 to 4.17.21

# Docs update
docs(contributing): add commit message guidelines

# Test coverage
test(cart): add edge cases for zero-quantity items

# CI pipeline change
ci: cache node_modules in GitHub Actions workflow

# Performance
perf(images): lazy-load hero images below the fold

Your Next Steps

  1. Bookmark the cheatsheet table above
  2. Add commitlint + husky to your next project
  3. Try git cz for one week — it builds the habit fast
  4. Once your history is clean, wire up semantic-release and let your CI handle versioning

Continue Learning — The Git Series

This post covers the commit format. For the full picture on writing commits that are genuinely useful to read later, go here:

Conventional Commits: The Complete Guide with Cheatsheet

Oh hi there 👋
It’s nice to meet you.

Sign up to receive awesome content in your inbox.

We don’t spam! Read our privacy policy for more info.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

3 Comments