A commit message is the signature on your code snapshot! It determines how readable the project history will be.
The Good Message Formula
<type>: <short description>
[optional longer description]
[optional footer]
Types:
- feat — new feature
- fix — bug fix
- docs — documentation
- refactor — refactoring without behavior change
- test — tests
- chore — routine tasks
- style — code formatting
Message Examples
Examples of Great Messages
✅ feat: add user authentication
✅ fix: resolve crash on empty input
✅ docs: update API documentation
✅ refactor: simplify database queries
✅ test: add unit tests for login
✅ chore: update dependencies
Examples of Bad Messages
❌ update
❌ fix
❌ done
❌ asdf
❌ commit
❌ stuff
Why they’re bad: A month from now YOU won’t remember what you did!
Writing Rules
1. First line — short description (50 characters)
# ✅ Good
feat: add two-factor authentication
# ❌ Bad (too long)
feat: add super amazing two-factor authentication with SMS and email support and a bunch of other stuff
2. Use the imperative mood
# ✅ Correct
fix: resolve memory leak in cache
feat: add export to PDF
docs: update installation guide
# ❌ Wrong
fix: resolved memory leak
feat: added export to PDF
docs: updated installation guide
Why: The commit makes a change, it doesn’t describe what you did.
3. Separate the subject from the body with a blank line
git commit -m "feat: add payment processing
Integrate Stripe API for payments.
Support credit cards and bank transfers. Support refunds and webhooks.
"
4. Explain “why”, not “what”
❌ Bad (describes WHAT):
fix: change timeout from 30 to 60
✅ Good (explains WHY):
fix: increase API timeout to prevent failures
30 seconds was too short for slow connections.
Users in remote areas experienced timeouts.
Increased to 60s based on metrics.
Commit Message Template
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
Example:
fix(auth): prevent duplicate user registration
Modified the registration endpoint to check for existing email
before creating a new user. Added unique constraint on email field
in database schema.
Fixes #453
When to Use a Detailed Description?
Short message is enough:
docs: fix typo in README
style: format code with prettier
chore: update package.json
Detailed description is needed:
refactor: redesign authentication flow
Old flow had security vulnerabilities:
- Session tokens stored in localStorage
- No CSRF protection
- Weak password requirements
New implementation:
- HttpOnly cookies for tokens
- CSRF tokens on all forms
- Enforced password complexity
- Rate limiting on login attempts
Breaking change: Need to clear browser data after update.
BREAKING CHANGE: Auth API changed from v1 to v2
Examples by Type
feat (new feature)
feat: add dark mode theme
feat: implement real-time notifications
feat(api): add GraphQL support
fix (bug fix)
fix: resolve crash on iOS Safari
fix: prevent XSS in user input
fix(payment): handle declined cards properly
docs (documentation)
docs: add deployment guide
docs: update API examples
docs(readme): add badges and shields
refactor
refactor: extract validation to separate module
refactor: use async/await instead of callbacks
refactor(db): optimize query performance
test
test: add unit tests for auth service
test: increase code coverage to 80%
test(api): add integration tests
chore
chore: update dependencies
chore: configure CI/CD pipeline
chore(git): add .gitignore rules
Linking to Issues and Tasks
# Reference an issue
fix: resolve login timeout issue
Fixes #123
# Breaking change
feat!: redesign API authentication
BREAKING CHANGE: API v1 deprecated, use v2 endpoints
GitHub automatically:
- Links the commit to the issue
- Closes the issue on merge (Fixes #123)
- Shows the link in the UI
Conventional Commits with Emoji (optional)
Some teams use emoji:
✨ feat: add new feature
🐛 fix: bug fix
📝 docs: documentation
♻️ refactor: code refactoring
✅ test: testing
🔧 chore: configuration
💄 style: styling
Example:
git commit -m "✨ feat: add user profile page"
Linting Tools and Checklist
Commitlint — automatic validation:
npm install --save-dev @commitlint/cli @commitlint/config-conventional
Husky — pre-commit check:
npx husky add .husky/commit-msg 'npx commitlint --edit $1'
Commit Message Checklist
- [ ] Starts with a type (feat, fix, docs, etc.)
- [ ] First line < 50 characters
- [ ] Imperative mood (“add” not “added”)
- [ ] Clear about what changed
- [ ] Detailed description added if complex
- [ ] Reference to issue/task if applicable
- [ ] No typos
Examples of Great Commit Histories
Django project:
feat: add user authentication system
feat: create registration form
feat: implement email verification
fix: resolve CSRF token mismatch
test: add auth tests
docs: update README with auth setup
refactor: extract email sender to service
chore: add Django extensions
Conclusion
Good commit messages are a mark of a professional!
Employers look at your GitHub. Write messages as if your boss will read them! 💼
Remember:
1. Type + short description
2. Imperative mood
3. Explain “why”
4. Reference issues
Start right now — make your next commit the right way! ✍️
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!