name: commit-forge description: Write clean, atomic git commits with conventional format. Use when committing code, staging changes, or user says "commit", "commit this", "stage and commit", or is done with a task and needs to commit. NOT for git troubleshooting or branch management.
Commit Forge
Atomic, descriptive git commits. Every commit is one logical change that leaves the codebase working.
Hard Rules
- NEVER commit without the user explicitly asking
- NEVER add co-author tags to commits
- NEVER skip hooks (
--no-verify,--no-gpg-sign) - NEVER force push to main/master
- NEVER use
git add .orgit add -A- stage specific files by name - PREFER creating a new commit over amending an existing one
Commit Message Format
type(scope): short description (max 72 chars)
Optional body - what and why, not how.
Optional footer - breaking changes, issue refs.
Types
| Type | Use For |
|---|---|
feat |
New feature or capability |
fix |
Bug fix |
docs |
Documentation only |
refactor |
Code restructuring, no behavior change |
test |
Adding or fixing tests |
chore |
Maintenance, deps, config, CI |
style |
Formatting, no logic change |
perf |
Performance improvement |
Scope
Use short, lowercase scope matching the area of change. Read the repo's existing commits (git log --oneline -20) to match the project's conventions.
Examples
feat(auth): add JWT refresh token rotation
fix(parser): handle empty broker email attachments
refactor(cli): extract table renderer to shared package
chore: update go dependencies
test(api): add integration tests for driver matching
Process
Step 1: Review Changes
git status
git diff
git diff --staged
Understand what changed before staging anything.
Step 2: Stage Selectively
Stage files that belong to one logical change:
git add src/auth/handler.go
git add src/auth/handler_test.go
If the diff contains multiple unrelated changes, split into separate commits.
Step 3: Verify Before Commit
Auto-detect and run the repo's checks:
| Indicator | Command |
|---|---|
Makefile with test target |
make test |
package.json with test script |
npm test / pnpm test |
go.mod exists |
go test ./... |
Cargo.toml exists |
cargo test |
pyproject.toml / setup.py |
pytest |
Only run if tests exist and are fast. Skip if the user explicitly says to commit without testing.
Step 4: Commit
Write a message that answers "what changed and why" - not "how."
git commit -m "feat(auth): add rate limiting to login endpoint"
For complex changes, use a body:
git commit -m "refactor(api): split monolithic handler into middleware chain
Request validation, auth, and response formatting were tangled
in a single 400-line handler. Split into composable middleware
for independent testing and reuse."
Step 5: Verify
git log --oneline -3
git show --stat
Confirm the commit looks right.
What Makes a Good Commit
| Good | Bad |
|---|---|
| One logical change | Multiple unrelated changes |
| All tests pass | Breaks something |
| Message says why | Message says "update stuff" |
| Can be reverted cleanly | Reverting would break other things |
| Specific files staged | git add . |
What Makes a Bad Commit Message
- "fix stuff" / "update" / "changes" / "WIP"
- Using "and" to describe two unrelated things
- Describing how instead of what/why
- Over 72 characters in the subject line
Checklist
Before committing:
- Changes are atomic (one logical unit)
- Specific files staged (not
git add .) - Tests pass (if applicable)
- Message follows
type(scope): descriptionformat - No co-author tags
- No sensitive files staged (.env, credentials, keys)