Split the current working tree changes into clean, atomic commits — each one focused on a single logical change.
Scope
Determine which changes to process:
- •If
$ARGUMENTScontains--staged, only consider staged changes (git diff --cached) - •If
$ARGUMENTScontains--all, consider all changes including untracked files (git diff+git ls-files --others --exclude-standard) - •Default (no arguments): consider all tracked changes, both staged and unstaged (
git diff HEAD)
Step 1: Analyze All Changes
- •Run
git statusto get an overview - •Run
git diff HEAD --statto see which files changed and by how much - •Run
git diff HEADto read the full diff - •If there are untracked files and
--allwas passed, read those files too
Build a mental model of every change in the working tree.
Step 2: Identify Logical Change Groups
Categorize every hunk and file change into logical groups. Each group should represent one cohesive purpose. Common groupings:
| Group Type | Examples |
|---|---|
| Feature | New component, new API endpoint, new utility function |
| Bug fix | Fix a specific bug (include related test fix) |
| Refactor | Rename, extract function, restructure — no behavior change |
| Style/format | Whitespace, formatting, linting fixes |
| Tests | New or updated tests (unless tightly coupled with a feature) |
| Config | Package.json, tsconfig, ESLint, env changes |
| Schema/migration | Database schema changes and generated migrations |
| Types | Type definition additions or changes |
| Docs | Documentation, comments, README updates |
| Deps | Dependency additions, removals, or version bumps |
| Cleanup | Remove dead code, unused imports, deprecated features |
Grouping Rules
- •A file can be split across groups — different hunks in the same file may belong to different logical commits
- •Related changes stay together — a new function and its tests go in the same commit (unless the test file is large and standalone)
- •Schema + migration are one commit — never separate a schema change from its migration
- •Import changes follow their usage — adding an import belongs with the code that uses it
- •Minimum viable commit — each commit should build and pass lint on its own (no broken intermediate states)
Step 3: Determine Commit Order
Order commits so that:
- •Dependencies come first — package.json/lock changes before code that uses new deps
- •Schema before code — database changes before code that relies on them
- •Types before implementation — type definitions before code that uses them
- •Refactors before features — restructuring before new functionality that builds on it
- •Core before consumers — utilities/libs before components that use them
- •Tests with or after their subject — never before the code they test
Step 4: Present the Plan
Show the user the proposed commit sequence:
## Atomic Commit Plan ### Commit 1: <type>: <description> Files: - `path/to/file.ts` (specific hunks: lines X-Y) - `path/to/other.ts` (entire file) Changes: <brief summary of what this commit does> ### Commit 2: <type>: <description> Files: - `path/to/file.ts` (specific hunks: lines A-B) Changes: <brief summary> ... ### Summary - Total commits: N - Order: deps → schema → types → refactor → feature → tests → cleanup
Commit Message Format
Use conventional commit style:
<type>: <concise description> <optional body explaining why, not what> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Types: feat, fix, refactor, style, test, config, schema, docs, deps, chore
Step 5: Get User Approval
Ask the user:
- •"Proceed with this plan?" — execute all commits as proposed
- •"Modify the plan" — let them adjust groupings, ordering, or messages
- •"Merge some commits" — combine groups if they prefer fewer commits
Wait for confirmation before making any commits.
Step 6: Execute Commits
For each commit in the plan:
- •Reset the staging area:
git reset HEAD(only before the first commit if things are staged) - •Stage precisely:
- •For entire files:
git add <file> - •For specific hunks:
git add -p <file>is interactive, so instead usegit diff > /tmp/patch.diff, then craft patches and apply withgit apply --cached - •For new files:
git add <file>
- •For entire files:
- •Verify staging: Run
git diff --cached --statto confirm only the intended changes are staged - •Commit: Create the commit with the planned message using a HEREDOC:
bash
git commit -m "$(cat <<'EOF' <type>: <description> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> EOF )"
- •Verify: Run
git log --oneline -1to confirm
Handling Partial File Staging
When a file needs to be split across commits, use this approach:
- •Save the full diff for the file:
git diff HEAD -- <file> > /tmp/full.patch - •For each commit involving this file, stage only the relevant hunks using
git add -por by crafting a targeted patch - •If interactive staging is needed, explain to the user which hunks to accept (s/y/n at each prompt)
Important: If precise hunk staging is too complex for a particular split, tell the user and suggest they manually stage with git add -p for that specific file, then you'll continue with the remaining commits.
Step 7: Final Summary
After all commits are created, show:
## Commits Created 1. abc1234 feat: add user avatar component 2. def5678 test: add avatar component tests 3. ghi9012 refactor: extract image utility from profile Run `git log --oneline -N` to review.
Edge Cases
- •No changes: If the working tree is clean, report that and exit
- •Single logical change: If everything belongs in one commit, say so and create a single well-messaged commit
- •Merge conflicts in staging: If partial staging creates issues, fall back to whole-file staging and explain the trade-off
- •Pre-commit hooks: If a commit fails due to hooks, fix the issue and retry (create a NEW commit, never amend a previous one)