Writing Clean Git Commit Messages
Good commit messages help teams understand code changes and project history.
Conventional Commits Format
<type>(<scope>): <subject>
<body>
<footer>
Types
| Type | Description | Example |
|---|---|---|
feat |
New feature | feat(auth): add OAuth2 support |
fix |
Bug fix | fix(player): prevent audio overlap |
docs |
Documentation | docs(readme): update installation steps |
style |
Formatting | style(components): format with prettier |
refactor |
Code change | refactor(services): extract validation logic |
test |
Adding tests | test(audio): add duration calculation tests |
chore |
Maintenance | chore(deps): update dependencies |
Subject Line
- Imperative mood: "add" not "added" or "adds"
- 50 characters or less: Keep it concise
- No period: At the end
- Lowercase after type:
feat(auth):notfeat(Auth):
✅ Good: feat(auth): add OAuth2 support
❌ Bad: Added OAuth2 support
❌ Bad: feat(Auth): Add OAuth2 Support.
Body
- Wrap at 72 characters: For readability
- Explain what and why: Not how
- Use present tense: "Change" not "changed"
Add support for YouTube OAuth2 authentication to enable video
uploads. This replaces the previous API key approach with a more
secure token-based system.
The new flow:
1. User initiates OAuth flow
2. Browser opens for consent
3. Access token stored locally
4. Token refreshed automatically
Footer
- Reference issues:
Closes #123 - Breaking changes:
BREAKING CHANGE: API endpoint changed
Closes #456
Co-Authored-By: Claude <noreply@anthropic.com>
Complete Example
feat(services): add cost tracking for Gemini API calls
Implement cost estimation and tracking for all AI operations to help
manage budget effectively. This includes:
- Token counting for input/output
- Per-model pricing calculations
- Cumulative cost tracking by operation
- Budget alerts when approaching limits
This allows users to monitor and optimize their API usage.
Closes #123
Co-Authored-By: Claude <noreply@anthropic.com>
Multi-Commit Changes
For larger changes, organize into logical commits:
1. refactor(audio): extract AudioService from pipeline
2. test(audio): add 21 unit tests for AudioService
3. refactor(pipeline): use new AudioService
4. docs(readme): document audio service extraction
Commit Message Template
#!/bin/bash
# Save as .git/hooks/prepare-commit-msg
commit_msg=$(cat "$1")
# Check for conventional commit format
if ! echo "$commit_msg" | grep -qE '^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: '; then
echo "Invalid commit message format!"
echo "Use: type(scope): subject"
echo ""
echo "Types: feat, fix, docs, style, refactor, test, chore"
exit 1
fi
# Check subject length
subject=$(echo "$commit_msg" | head -n1)
if [ ${#subject} -gt 50 ]; then
echo "Subject line too long (max 50 characters)"
exit 1
fi
Interactive Rebase for Cleanup
# Rebase last 5 commits
git rebase -i HEAD~5
# Commands:
# pick = use commit
# reword = edit message
# edit = pause for changes
# squash = merge into previous
# drop = remove commit
Co-Authored-By Attribution
For AI-assisted development:
fix(video): correct frame calculation for cross-fades
The previous calculation didn't account for the 30-frame overlap
between consecutive scenes, causing timing issues.
Co-Authored-By: Claude <noreply@anthropic.com>
Common Mistakes to Avoid
| ❌ Bad | ✅ Good |
|---|---|
update stuff |
feat(api): add rate limiting |
fix bug |
fix(player): prevent audio overlap |
wip |
refactor(ui): extract header component |
finished feature |
feat(auth): add OAuth2 support |
fixed it |
fix(api): handle timeout errors |
Branch Naming
feat/add-oauth2-support
fix/player-timing
docs/update-readme
refactor/extract-services
Summary Checklist
- Type is one of: feat, fix, docs, style, refactor, test, chore
- Subject is < 50 characters
- Subject uses imperative mood
- Body wraps at 72 characters
- Body explains what/why (not how)
- Footer references issues (if applicable)
- No trailing whitespace
- Blank line between subject and body
- Co-Authored-By for AI assistance