Commit Message Conventions

A well-written commit message is one of the most underrated tools in software development. It tells the story of your code—why changes were made, not just what changed. Learn the Conventional Commits standard and best practices for writing clear, meaningful commit messages.

Commit Types Scopes Breaking Changes
Why Commit Messages Matter

Commit messages are the historical record of your project. Months or years from now, you'll look at the git log to understand why something was changed. A good commit message answers the question "Why?" not just "What?" The "what" is already visible in the code diff. The "why" is what matters for future developers.

Good commit messages help with code review, debugging (finding when a bug was introduced), understanding rationale, generating changelogs automatically, and onboarding new team members. They also improve your team's ability to communicate about the codebase.

Teams that use consistent commit message conventions spend less time deciphering old code and generate better release notes automatically. It's a small investment with huge returns.
The Seven Rules of Great Commit Messages
  • 1. Separate subject from body with a blank line - The subject line is a summary; the body provides details.
  • 2. Limit the subject line to 50 characters - Short enough to be readable in git log --oneline.
  • 3. Capitalize the subject line - Starts with a capital letter, like a sentence.
  • 4. Do not end the subject line with a period - Save the space for content.
  • 5. Use the imperative mood in the subject line - Write as if giving a command: "Fix bug" not "Fixed bug" or "Fixes bug".
  • 6. Wrap the body at 72 characters - Git doesn't wrap text; do it manually for readability.
  • 7. Use the body to explain what and why vs. how - The how is in the diff.
Example following all rules:
Fix calculation error in tax calculator

The tax calculation was incorrectly using the subtotal after discount
but before shipping. This caused incorrect tax amounts for orders
with free shipping.

Fixed by moving the tax calculation after all discounts are applied.
Added tests for the free shipping edge case.
Conventional Commits: The Industry Standard

Conventional Commits is a lightweight convention for commit messages that enables automatic changelog generation and semantic versioning. The format is simple: <type>[optional scope]: <description>, followed by an optional body and footer.

Core commit types: feat - a new feature (triggers a minor version bump), fix - a bug fix (triggers a patch version bump), docs - documentation changes, style - formatting, whitespace, etc. (no code change), refactor - code change that neither fixes a bug nor adds a feature, perf - performance improvement, test - adding or updating tests, chore - maintenance tasks (build process, dependencies).

Use ! after the type/scope to indicate a breaking change: feat(api)!: change response format (triggers a major version bump).

feat(auth): add social login with Google

Implement OAuth2 integration for Google authentication.
Users can now sign in using their Google accounts.
Added new environment variables for client ID and secret.


Closes #142
Commit Types Reference
TypeDescriptionVersion Impact
featNew feature for the userMinor (x.Y.z)
fixBug fix for the userPatch (x.y.Z)
docsDocumentation changesNone
styleFormatting, missing semicolons, etc.None
refactorCode change that neither fixes bug nor adds featureNone
perfPerformance improvementPatch
testAdding missing tests or correcting testsNone
choreBuild process or auxiliary tool changesNone
ciCI/CD configuration changesNone
BREAKING CHANGEBreaking API changeMajor (X.y.z)
Writing Effective Subject Lines

The subject line is the first line of the commit message, limited to 50 characters. It should complete the sentence "If applied, this commit will..." Use the imperative mood: "Fix" not "Fixed" or "Fixes". Be specific but concise.

feat: add user profile editing
fix: resolve null pointer in login flow
docs: update API documentation for v2
perf(api): reduce response time by caching
refactor: extract validation logic to helper
Pro tip: Use git commit -m "subject" -m "body" to easily create multi-line commit messages with a blank line between subject and body.
Writing the Commit Body

The body should explain what changed and why, not the mechanics of the change. Focus on the problem being solved and the approach taken. Ask yourself: "If I read this commit message in six months, will I understand the reasoning?"

Wrap lines at 72 characters. Use bullet points for multiple changes or reasons. Mention ticket numbers, related issues, or previous commits that are relevant.

fix: correct tax calculation for free shipping orders

The tax calculation was applied before the free shipping discount,
causing incorrect tax amounts for orders with free shipping.

This affected all orders over $50 where free shipping applies.

Changes made:
- Move tax calculation after all discounts
- Add test for free shipping tax calculation
- Update documentation for calculation order


Fixes #245
Breaking Changes

When a change breaks backward compatibility, mark it clearly. In Conventional Commits, add a ! after the type/scope, or add a BREAKING CHANGE: footer. This triggers a major version bump in automated semantic versioning tools.

feat(api)!: change response format to match OpenAPI spec

The API now returns consistent error objects and uses camelCase
for all fields. Previous snake_case fields are still available
temporarily but will be removed in v3.0.


BREAKING CHANGE: Response format changed from snake_case to camelCase
Good vs Bad Commit Messages
❌ Bad✅ Good
"fix bug""fix: correct null pointer when user session expires"
"update""feat(profile): add avatar upload functionality"
"changed stuff""refactor: extract payment validation to dedicated service"
"fixed tests""test: add integration tests for checkout flow"
"more changes""perf: lazy-load images on homepage"
A good commit message should be understood by someone who isn't familiar with the specific codebase. Assume the reader knows the language but not the business context.
Tooling and Automation

Enforce commit conventions with automated tools. Commitlint checks commit messages against rules. Husky runs lint-staged and commitlint on git hooks. Semantic-release automatically bumps versions and generates changelogs from Conventional Commits.

# Install commitlint and husky npm install --save-dev @commitlint/cli @commitlint/config-conventional husky # commitlint.config.js module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'subject-case': [2, 'never', ['start-case', 'pascal-case']], 'subject-max-length': [2, 'always', 50] } };
Automatic Changelog Generation

One of the biggest benefits of Conventional Commits is automatic changelog generation. Tools like standard-version or semantic-release scan commit history and produce formatted changelogs grouped by type (Features, Bug Fixes, Performance Improvements, Breaking Changes, etc.).

# Changelog

## 1.2.0 (2024-03-15)

### Features
- add user profile editing (abc1234)
- implement social login with Google (def5678)


### Bug Fixes
- correct tax calculation for free shipping (ghi9012)
- resolve null pointer in login flow (jkl3456)
A well-maintained changelog makes it easy for users and contributors to understand what changed in each release. It's a sign of a mature open source project.
Team Commit Message Guidelines
  • Agree on commit types as a team. Add custom types if needed (e.g., "ui", "i18n", "security").
  • Enforce conventions with commitlint in CI. Reject commits that don't follow the format.
  • Use scopes to indicate the area of the codebase (e.g., "auth", "api", "database").
  • Keep commits focused. One logical change per commit. If you need "and" in the description, split into multiple commits.
  • Write commit messages before writing code. It helps clarify what you're trying to accomplish.
  • Squash WIP commits before merging. A feature branch doesn't need 15 "WIP" commits in the final history.
Frequently Asked Questions
How do I fix a bad commit message after committing?
Use git commit --amend to edit the most recent commit message. For older commits, use git rebase -i HEAD~N and use "reword" on the commit. Never rewrite history on shared branches.
Should I capitalize the first letter of the subject line?
Yes, the subject line should be capitalized. This follows standard sentence capitalization and improves readability. "Fix login bug" not "fix login bug".
Do I need to use Conventional Commits for personal projects?
It's less critical but still helpful. Good commit messages help future you understand why changes were made. For projects you'll revisit months later, it's worth the effort.
What if my team uses a different commit convention?
Consistency is more important than which convention you choose. Pick one standard (Conventional Commits is widely adopted) and enforce it across the team.
How do I reference issues in commit messages?
Use the commit footer: Closes #123 or Fixes #456. GitHub automatically links the commit to the issue and closes it when the commit is merged to main.
What should I do if a commit touches multiple concerns?
Split it into multiple commits. Use git add -p to stage parts of files. Each commit should represent one logical change. If you're describing the change with "and," it's probably two commits.
How do I write a commit message for a revert?
Use git revert which automatically creates a commit message like "Revert 'previous commit message'". You can add additional explanation in the body about why the revert is needed.
Can I write commit messages in languages other than English?
It's best to use English for consistency, especially if your team or users are international. English is the common language of code. If your team is all native speakers of another language, consistency within the team matters most.
Quick Reference Cheatsheet
<type>(<scope>): <subject> <BLANK LINE> <body> <BLANK LINE> <footer> Example: feat(auth): add biometric login support Implement fingerprint and face recognition login using the device's biometric hardware. Closes #342
Remember: The subject line should be ≤50 characters, start with a capital letter, use imperative mood, and no period at the end.
Previous: GitHub Flow Best Practices Next: GitHub CLI Cheatsheet

Great commit messages tell the story of your project. They make git log a valuable resource rather than a mystery. Invest in your commit messages—they pay dividends for years.