| name | split-commits-by-diff |
| description | Split Git commits by diff hunks to create clean, scoped changes. |
Split Commits by Diff
Use this skill to turn a mixed working tree into clean, scoped commits.
Outcomes
- Produce a commit plan before touching the index.
- Keep each commit focused on one intent (feature, fix, refactor, docs, test, chore).
- Preserve user changes while avoiding accidental staging.
- Create clear commit messages that explain why each commit exists.
Safety Rules
- Never run destructive git commands (
reset --hard, checkout --, force push) unless the user explicitly asks.
- Never rewrite history (
commit --amend, rebase) unless the user explicitly asks.
- Never commit secrets or credential-like files (
.env, key files, token dumps).
- If pre-commit hooks modify files, include those modifications in a new commit unless the user asks otherwise.
- If there are no real changes, do not create an empty commit.
Workflow
1) Inspect the repository state
Run these first:
git status --short
git diff
git diff --cached
git log -n 12 --pretty=format:"%h %s"
Understand:
- Which files are changed and whether they are staged or unstaged.
- Whether the changes represent one concern or multiple concerns.
- The repository's commit message style.
2) Build a commit grouping plan
Create a grouping proposal before staging:
- Group by intent, not only by file path.
- Keep dependent changes together when splitting would break tests/build.
- Prefer 2-6 commits for a medium mixed diff. Avoid over-splitting tiny edits.
For each proposed group, define:
- Group name (short)
- Files/hunks included
- Rationale (why this grouping is coherent)
- Commit message draft
If one hunk belongs to a different intent than the rest of the file, use patch staging.
3) Stage only the intended changes for one group
Default staging strategy:
- Full-file stage when file is single-intent:
git add <file>
- Hunk-level stage when file is mixed-intent:
git add -p <file>
If interactive hunk selection is unavailable in the runtime, use this fallback:
- Stage full file.
- Unstage unintended hunks or file parts with
git restore --staged for specific files.
- Iterate until
git diff --cached matches the current group exactly.
4) Commit the current group
Commit with a concise message aligned to repo style.
Message guidance:
- First line: short imperative summary.
- Optional body: 1-2 lines explaining why.
- Prefer semantic prefixes only if repository already uses them.
Example styles:
fix(auth): avoid duplicate refresh token writes
refactor(blog): extract locale normalization helper
docs: clarify cache invalidation workflow
5) Validate and continue
After each commit:
git show --stat --oneline -1
git status --short
Then repeat staging and commit for the next group until complete.
6) Final verification
At the end, run:
git log --oneline -n <number_of_new_commits>
git status
Report:
- Number of commits created
- Commit subjects in order
- Remaining uncommitted files (if any)
Decision Heuristics
When splitting is ambiguous, prioritize in this order:
- Keep the repository buildable/testable after each commit.
- Keep one conceptual change per commit.
- Keep reviewer readability high.
- Minimize risky partial staging.
Do not force perfect atomicity if it causes fragile or misleading commits.
Communication Contract
When invoked, communicate in this sequence:
- Briefly summarize current diff shape.
- Show proposed commit groups.
- Execute staging + commit per group.
- Report final commit list and remaining state.
Be decisive. Only ask for user input when there are multiple equally valid split strategies that materially change history.