Writing Git Commits
Write clear, professional Git commit messages following Tim Pope's style guide.
Quick Start
/commit # Invoke when ready to commit staged changes /commit --amend # Amend the previous commit message
The Iron Law
NEVER reference Claude, Anthropic, AI, or any AI attribution in commit messages.
- •No "Co-Authored-By: Claude" lines
- •No "Generated by AI" notes
- •No "Claude suggested" comments
- •No AI tools mentioned anywhere
This is non-negotiable. Violating this rule fails the entire commit.
Template Lookup (Dynamic)
Before writing a commit message, check for project-specific templates:
- •Git config template:
git config commit.template - •Repo root:
.gitmessagefile in repository root - •Existing template comments:
.git/COMMIT_EDITMSG - •Fallback: Tim Pope format (documented below)
If a project template exists, follow its conventions. Otherwise, use Tim Pope format.
Tim Pope Format
The Seven Rules
- •Subject ~50 chars (hard max: 72)
- •Capitalize the subject line
- •No period at end of subject
- •Imperative mood in subject ("Add" not "Added" or "Adds")
- •Blank line separating subject from body
- •Wrap body at 72 chars
- •Body explains what/why, not how
The Completion Test
Every subject line must pass this test:
"If applied, this commit will [your subject line]"
Examples:
- •"If applied, this commit will Add user authentication" ✓
- •"If applied, this commit will Fixed the bug" ✗
- •"If applied, this commit will Refactor payment module for clarity" ✓
Subject Line Verbs
| Verb | Use For |
|---|---|
| Add | New feature, file, or capability |
| Remove | Deleting code, files, or features |
| Fix | Bug fixes |
| Update | Changes to existing functionality |
| Refactor | Code restructuring without behavior change |
| Rename | Renaming files, variables, functions |
| Move | Relocating code or files |
| Extract | Breaking out code into new function/module |
| Simplify | Reducing complexity |
| Improve | Performance, readability, or UX enhancements |
| Replace | Swapping one implementation for another |
| Support | Adding capability for something |
| Handle | Adding case handling or error handling |
| Implement | Completing a feature or specification |
| Configure | Setting up config or environment |
| Document | Adding or updating documentation |
When to Include a Body
- •Subject only: Single-purpose changes where the diff is self-explanatory
- •Subject + body: Multi-file changes, non-obvious decisions, breaking changes
Body content should answer:
- •What changed and why?
- •What alternatives were considered?
- •What are the consequences or side effects?
- •Are there any caveats or known issues?
Workflow
Step 1: Gather Context
Use atomic-thought to decompose the changes:
What files changed? What was the purpose of each change? What's the unifying theme?
Step 2: Draft Subject Line
Use chain-of-thought to craft the subject:
- •Identify the primary action (verb)
- •Identify the primary object (what was affected)
- •Combine into imperative statement
- •Check length (~50 chars)
- •Apply completion test
Step 3: Draft Body (if needed)
For non-trivial changes:
- •Explain what changed at a high level
- •Explain why the change was necessary
- •Note any consequences or caveats
- •Keep lines at 72 characters
Step 4: Validate
Use self-consistency to verify:
- • Subject passes completion test
- • Subject is imperative mood
- • Subject is capitalized, no period
- • Subject ~50 chars (never >72)
- • Blank line before body (if body exists)
- • Body wraps at 72 chars
- • Body explains what/why not how
- • Zero AI attribution
Step 5: Commit
Format commit message using HEREDOC for proper formatting:
git commit -m "$(cat <<'EOF' Subject line here Body paragraph explaining what changed and why. Wrap at 72 characters per line. EOF )"
Examples
Good: Simple Change
Add null check in user validation
Good: With Body
Refactor authentication to use JWT tokens Replace session-based auth with stateless JWT tokens to support horizontal scaling. Sessions required sticky load balancing which complicated our deployment. JWTs allow any server to validate requests independently. Breaking change: existing sessions will be invalidated on deploy.
Good: Bug Fix
Fix race condition in order processing Multiple concurrent orders could decrement inventory below zero because the check-then-update wasn't atomic. Use database-level locking to ensure inventory never goes negative. Fixes #1234
Bad Examples
fixed bug # Not capitalized, not specific Updated the code. # Period, vague Add feature for handling users. # Period adds new authentication system # Not capitalized, not imperative WIP # Not descriptive Misc fixes # Too vague Co-Authored-By: Claude <...> # AI ATTRIBUTION - NEVER DO THIS
Issue References
Place issue references at the end of the body:
Fix memory leak in image processing The resize operation wasn't releasing the source image buffer after completion, causing memory to grow unbounded. Fixes #456 Closes #457 Refs #400
Breaking Changes
Call out breaking changes prominently:
Remove deprecated v1 API endpoints BREAKING CHANGE: The /api/v1/* endpoints are removed. Clients must migrate to /api/v2/* which has been available since release 2.0. Migration guide: docs/migration-v1-to-v2.md
Multiple Related Changes
If a commit touches multiple things, the subject should capture the theme:
Improve error handling across payment flow - Add retry logic for transient gateway failures - Log detailed error context for debugging - Return user-friendly error messages - Add circuit breaker for repeated failures
Success Checklist
Before finalizing any commit message, verify:
- • Subject passes: "If applied, this commit will [subject]"
- • Subject uses imperative mood (Add/Fix/Update, not Added/Fixed/Updated)
- • Subject starts with capital letter
- • Subject has no trailing period
- • Subject is ~50 characters (hard max 72)
- • Blank line between subject and body
- • Body lines wrap at 72 characters
- • Body explains what/why, not how
- • No AI attribution anywhere
- • Issue references at end of body (if applicable)