Analyzes git changes and creates well-structured, atomic commits following project conventions. Detects commit style, plans optimal commit grouping, and ensures proper separation of concerns.
Hard Rule:
Split by: directory, concern, component type, or revertability
Combine only when:
Self-check before committing:
"Am I making 1 commit from 3+ files?" → STOP AND SPLIT
Run in parallel:
git status && git diff --staged --stat && git diff --stat
git log -30 --oneline && git log -30 --pretty=format:"%s"
git branch --show-current
git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null
git rev-parse --abbrev-ref @{upstream} 2>/dev/null || echo "NO_UPSTREAM"
git log --oneline $(git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null)..HEAD 2>/dev/null
Gather: changed files, recent commit style, branch state, upstream tracking, local commits
After gathering context, ALWAYS sync with upstream before making any changes:
git pull --rebase
If conflicts occur:
Proceed only when:
git pull --rebase completes without conflicts, ORAnalyze last 30 commits:
git log -30 --pretty=format:"%s"
Detection rules:
| Style | Pattern | Example | Regex |
|---|---|---|---|
SEMANTIC |
type: message |
feat: add login |
`/^(feat |
PLAIN |
Description only | Add login feature |
No prefix, >3 words |
SHORT |
1-3 words | format, lint |
^\w+(\s+\w+){0,2}$ |
Decision:
IF semantic >= 50% → SEMANTIC
ELSE IF short >= 30% → SHORT
ELSE → PLAIN
Output before proceeding:
STYLE: [SEMANTIC | PLAIN | SHORT]
Examples: [3 actual messages from log]
Current branch: <name>
Upstream: true | false
Local commits: N
On main/master: true | false
Strategy:
main/master → NEW_COMMITS_ONLY (never rewrite)Minimum commits: ceil(file_count / 3)
Split rules:
Example:
8 files:
app/page.tsx, app/layout.tsx → commit 1 (app layer)
components/demo/*.tsx → commit 2 (demo)
components/pricing/*.tsx → commit 3 (pricing)
e2e/*.spec.ts → commit 4 (tests)
messages/*.json → commit 5 (i18n)
Dependency order:
Level 0: utils, types, constants
Level 1: models, schemas
Level 2: services, business logic
Level 3: API endpoints
Level 4: config, infrastructure
Output plan:
COMMIT PLAN
===========
Files: N | Min commits: M | Planned: K | Status: PASS/FAIL
Commit 1: <message>
- file1.py, file1_test.py
Justification: implementation + test
Commit 2: <message>
- file2.py
Justification: independent utility
Order: Commit 1 → Commit 2 (Level 0 → Level 1)
Requirements:
Choose FIXUP when:
Choose NEW COMMIT when:
Reset & rebuild:
git reset --soft $(git merge-base HEAD main)
# Recommit in atomic units
Only if: all commits local + user allows
Final plan:
strategy: FIXUP_THEN_NEW | NEW_ONLY | RESET_REBUILD
commits:
- type: fixup/new
files: [...]
message: "..."
Fixup commits:
git add <files>
git commit --fixup=<hash>
# Repeat for all fixups
git rebase -i --autosquash $(git merge-base HEAD main)
New commits:
git add <files>
git commit -m "<message>" # Use detected style
Message format:
| Style | Format |
|---|---|
| SEMANTIC | feat: add login |
| PLAIN | Add login feature |
| SHORT | format, lint |
Validate: matches detected style + similar to git log examples
git status # Clean working directory
git log --oneline $(git merge-base HEAD main)..HEAD # Review history
Push strategy:
git push --force-with-leasegit pushFinal report:
Created: N commits | M fixups merged
History:
abc123 Add feature X
def456 Fix bug Y
Next: git push [--force-with-lease]
Style detection:
feat:, fix: → SEMANTICAdd, Fix → PLAINformat, lint → SHORTDecision tree:
main/master? → NEW_COMMITS_ONLY (never rewrite)
All local? → AGGRESSIVE_REWRITE OK
Pushed? → CAREFUL_REWRITE (warn on force push)
Complements existing? → FIXUP
New feature? → NEW COMMIT
Anti-patterns:
[ ] Min commits: ceil(N/3)?
[ ] Justified commits with 3+ files?
[ ] Different directories split?
[ ] Tests paired with implementation?
[ ] Dependency order correct?
Stop conditions: