Introduction
Git commits are more than technical records—they are a form of communication. Every commit you write tells a story to your future self and your team members. A well-structured commit message can save hours of debugging, provide crucial context during code reviews, and make your project history an invaluable resource rather than a cryptic puzzle.

In this guide, we'll explore the principles of effective commit messages and provide practical patterns you can implement immediately.
Why Good Git Commits Matter
The difference between a good commit and a bad one often seems trivial at first. But when you're investigating a production bug six months later, or trying to understand why a specific decision was made, the quality of your commit messages becomes critical.
The Business Case
Clear commits provide:
- Faster code reviews — Reviewers understand the intent without asking questions
- Better debugging —
git blameandgit logbecome your allies, not your adversaries - Smoother onboarding — New team members understand the evolution of the codebase
- Easier refactoring — Understanding why something was done helps decide how to change it
- Accountability — Proper attribution and context for every change
A well-maintained project history is as valuable as well-maintained code.
The Anatomy of a Professional Commit
A professional commit consists of three distinct parts:
1. Commit Type
The type prefix categorizes what kind of change you're making. This allows team members and tools to scan your history quickly.
feat: A new feature
fix: A bug fix
docs: Documentation changes only
style: Code style changes (formatting, semicolons, etc.)
refactor: Code refactoring without feature or bug changes
perf: Performance improvements
test: Adding or updating tests
chore: Build process, dependencies, or tooling changes
ci: CI/CD configuration changes
2. Subject Line
The subject is a brief, imperative summary of the change.
Rules for the subject line:
- Use the imperative mood (
Add, notAddedorAdds) - Do not capitalize the first letter
- Do not end with a period
- Limit to 50 characters maximum
- Make it specific and descriptive
Good examples:
feat: add email verification for user registration
fix: resolve null pointer exception in payment module
docs: update api documentation with auth examples
refactor: simplify recursive tree traversal algorithm
Bad examples:
feat: add some stuff
fix: fixes
updated things
work in progress
3. Body (Optional but Recommended)
The body provides detailed context about why the change was made, not what was changed (the diff shows that).
Guidelines for the body:
- Separate from the subject with a blank line
- Wrap at 72 characters for terminal compatibility
- Explain the why, not the what
- Reference related issues or tickets (
Closes #123) - Describe side effects or breaking changes
Example body:
The previous implementation used synchronous file I/O which blocked
the event loop during large file uploads. This change implements
async/await to prevent blocking and improve user experience.
Performance testing shows a 40% improvement in upload speed for
files over 10MB.
Closes #456
Related to #789
Real-World Examples
✅ Excellent Commit
feat: implement rate limiting for api endpoints
Add token bucket algorithm to prevent abuse and ensure fair
resource allocation across users. Rate limits are configurable
per endpoint and per user tier.
This prevents the API from being overwhelmed by poorly-behaved
clients while maintaining quality of service for legitimate users.
Limits are stored in Redis for distributed rate limit checking
across multiple server instances.
Closes #234
✅ Good Commit
fix: handle missing environment variables gracefully
Check for required env vars at startup and provide helpful error
messages instead of cryptic failures later in the application.
Resolves issue where deployment would fail silently if DATABASE_URL
was not set.
❌ Poor Commit
fix: stuff
updated code
❌ Poor Commit (Too Vague)
feat: improvements
fix: bugs
updated files
Best Practices & Pro Tips
1. One Commit = One Logical Change
Each commit should represent a single, complete idea. If you find yourself describing a commit with "and," it's probably too big.
✅ Good:
- feat: add password reset functionality
- feat: add email notification service
- test: add unit tests for auth module
❌ Bad:
- feat: add password reset and email notifications and update profile
2. Use Imperative Mood Consistently
✅ Correct:
- Add authentication
- Fix memory leak
- Improve performance
- Update dependencies
❌ Incorrect:
- Added authentication
- Fixed memory leak
- Improving performance
- Dependencies updated
3. Reference Issues and PRs
Make commits traceable to your issue tracking system:
Closes #234
Fixes #456
Resolves #789
Related to #101
4. Avoid These Common Mistakes
- Committing too much: Break large changes into focused commits
- Vague messages: Be specific about what changed and why
- Mixing concerns: Keep formatting fixes separate from logic changes
- Ignoring context: Assume the reader won't see your screen
5. Use a Template for Consistency
Many teams standardize commit messages with templates. Git allows you to set a default template:
git config commit.template ~/.gitmessage
Tools to Help You
Several tools can enforce commit message quality:
- Commitlint — Validates commit messages against rules
- Husky — Git hooks that prevent bad commits
- Conventional Commits — A specification for commit format
- GitKraken — Git GUI with commit templates
Conclusion
Good commit messages are a sign of a mature, professional development team. They reduce friction, improve code quality, and make your project history a valuable asset.
Start today: apply these principles to your next commit. Your future self will thank you.
Remember: A good commit is a gift to your future team.