Skill: Commit Rewriter
Rewrite commit messages in three phases: prepare, draft, apply. Follows .github/git-commit-instructions.md.
Scripts
Reusable scripts live in scripts/ relative to this SKILL.md:
| Script | Purpose |
|---|---|
scripts/build_rebase_todo.py | Parses commit_rewrite_mapping.md + git log, writes /tmp/rebase_todo.txt and /tmp/commit_msg_mapping.json. |
scripts/msg_filter.py | Reads /tmp/commit_msg_mapping.json; used as git filter-branch --msg-filter. |
scripts/verify.sh | Checks commit count and diffs against BACKUP branch. |
Process Overview
Phase 1 — Preparation
- Verify
<branch>-BACKUPexists; refuse to proceed if missing. - Detect branch point (
merge-baseor user-provided). - List commits; locate plan file (e.g.,
plan-*.md) or ask. - Report findings, wait for confirmation → Phase 2 — Analysis & Message Drafting.
Phase 2 — Analysis & Message Drafting
- Analyze
git --no-pager diff --statper commit. - Read the plan as context — diff stats take priority. Describe what actually changed, not what the plan intended.
- Map commits to plan steps (by file overlap and intent):
- At most one actual commit per plan step; unmapped is fine. - Mapped → title starts with Step X:. Unmapped → plain title.
- Generate new messages per
.github/git-commit-instructions.md. - Write
commit_rewrite_mapping.mdin the project root: # Old message New message Plan step Comments 1feat: add XStep 1: Add X to YStep 1 — 2fix typoFix typo in Z— merge with #1 3wip— — delete — empty commit Comments column: suggest merge/squash/delete where appropriate. - Report table, wait for confirmation → Phase 3 — Rewrite & Verify. User may edit the file before confirming; Phase 3 re-reads it and treats every change as authoritative (renamed titles, accepted/rejected merges, reassigned mappings).
Phase 3 — Rewrite & Verify
All commands below use SCRIPTS=.github/skills/pavlo-commit-rewriter/scripts.
- Stash uncommitted changes (rebase and filter-branch require a clean tree):
git stash --include-untracked - Generate rebase todo and message mapping:
python3 -u $SCRIPTS/build_rebase_todo.py \ --mapping commit_rewrite_mapping.md \ --branch-point <hash>This writes/tmp/rebase_todo.txtand/tmp/commit_msg_mapping.json. Review the printed summary (pick/fixup/drop counts). - Rebase (only if fixup or drop rows exist):
GIT_SEQUENCE_EDITOR="cp /tmp/rebase_todo.txt" \ git rebase -i <branch-point>Commit count decreases after rebase; the build script prints the expected count. - Rewrite messages:
cp $SCRIPTS/msg_filter.py /tmp/msg_filter.py FILTER_BRANCH_SQUELCH_WARNING=1 \ git filter-branch -f --msg-filter \ 'python3 /tmp/msg_filter.py /tmp/commit_msg_mapping.json' \ <branch-point>..HEAD - Verify:
bash $SCRIPTS/verify.sh <branch-point> <branch> <expected-count>
- Checks commit count matches expected. - Lists all rewritten messages. - Diffs against BACKUP; warns if non-empty.
- Restore stashed changes:
git stash pop
Rules
- No git pager. Every git command must use
git --no-pager. Baregit log/git diffblocks the agent. - Match by subject line, not hash (hashes change after rewrite/rebase).
- Commit count changes after rebase. Verify the new count (printed by
build_rebase_todo.py) before running filter-branch. - Named phases. Always name the next phase when asking for confirmation.
- User edits are authoritative. Phase 3 honours all changes the user made to
commit_rewrite_mapping.md. - Stash before rewrite. Phase 3 operations require a clean working tree. Stash before starting, pop after verification.
Related
.github/git-commit-instructions.md— commit message conventions.pavlo-commit-by-commit-execution— execution skill usingStep X:naming.