Reshape PR Commits
Turn a branch's messy WIP/fixup commit history into a clean, logically-grouped set of commits before review — proposed regrouping with explicit approval, git reset --soft plus staged re-commits instead of interactive rebase, and hard guardrails (feature branches only, force-with-lease only, never touch another author's commits).
A PR with fifteen commits named 'wip', 'fix', and 'oops typo' works fine to merge, but it makes the diff impossible to review commit-by-commit and turns git blame into archaeology — and the fix isn't interactive rebase's fragile editor dance, it's a three-command reset-and-recommit flow any agent can run safely with the right guardrails.
Who it's for: developers who batch small WIP commits while working and need a clean history before opening a PR, tech leads who want reviewable, logically-grouped diffs instead of a stream-of-consciousness commit log, teams standardizing on conventional commit messages before merge, anyone nervous about force-pushing history rewrites
Example
"Clean up my commits before I open this PR" → git log against the merge-base to see the noisy history, the combined diff read to understand what actually changed (not what the messages claim), a numbered regrouping plan presented for approval before anything is touched, then git reset --soft plus staged re-commits and a force-with-lease push
New here? 3-minute setup guide → | Already set up? Copy the template below.
# Reshape PR Commits
Turn the current branch's commit history into a set of commits that each represent one coherent logical change, with terse messages. Use when asked to tidy, squash, reshape, or clean up commits on the current branch or PR.
## Proactive Suggestion (When Not Explicitly Invoked)
When the user signals the PR is done — "done with this PR," "ready for review," "let's open the PR," or just before calling a PR-ready command — check `git log <base>..HEAD --oneline`. If the history is noisy (WIP/fixup/"oops" commits, or many tiny commits touching the same area), offer once: suggest cleaning up the commits before review. Accept either answer and move on; do not re-ask in the same session.
## Non-Negotiable Guardrails
- **Only ever rewrite the current feature branch.** Refuse if the branch is the main/default branch, or if the current HEAD is already merged.
- **Always `--force-with-lease`**, never plain `--force`, when pushing the rewritten history.
- Before touching history, surface the proposed final shape (one line per planned commit) and get explicit user approval.
- If the branch has commits from other authors, stop and ask — do not silently re-author someone else's work.
## Flow
1. **Identify the base.** `git merge-base HEAD origin/main` (or whatever branch the PR targets). Show `git log --oneline <base>..HEAD`.
2. **Read the combined diff.** `git diff <base>..HEAD` — understand what actually changed, not just what the existing commit messages claim.
3. **Propose a regrouping.** Rules:
- One commit per logical change. Unrelated files go in separate commits.
- Pure refactor and behavior change don't mix in the same commit.
- Test additions usually ride with the code they test, unless the user is landing tests separately on purpose.
4. **Present the plan** as a numbered list — `<type>(<scope>): <subject>` plus an optional one-line rationale for why that split exists. Wait for approval before touching anything.
5. **Execute with `git reset --soft <base>`**, followed by staged `git add` + `git commit` per group. Prefer this over interactive rebase — it's simpler, produces fewer merge conflicts, and skips the editor dance entirely.
6. **Push with `git push --force-with-lease`.**
## Commit Message Rules
Follow the project's own commit-message conventions (type prefix, scope, subject style, body policy) if a `CONTRIBUTING.md` or similar document defines them. Don't invent a scheme that conflicts with an existing house style.
## When in Doubt
If the user's intent for the split is ambiguous — "clean this up" against fifteen mixed commits — ask one clarifying question before proposing the plan. Don't guess at ten different groupings and hope one lands.
Get new playbooks like this one
One email a week with new Claude Code workflows. Free, like everything here.
No spam. Unsubscribe anytime.
What This Does
A disciplined workflow for turning a noisy feature-branch history into a small set of commits, each representing one coherent logical change, before a PR goes up for review. Rather than interactive rebase's fragile pick/squash/reword editor flow, it uses git reset --soft back to the merge-base followed by staged git add + git commit per logical group — simpler, with far fewer merge-conflict surprises. The flow always reads the combined diff first (not just the existing commit messages, which are often wrong or stale) before proposing a regrouping, then presents the planned final shape as a numbered list and waits for explicit approval before touching any history.
It also defines when to offer this proactively: when the user signals a PR is ready ("done with this PR," "let's open it") and the commit log looks like a stream of WIP/fixup commits, suggest the cleanup once — but never insist, and never re-ask in the same session if declined. The guardrails are the load-bearing part: only ever rewrite the current feature branch (refuse on main or an already-merged HEAD), always --force-with-lease on the push, and stop and ask rather than silently re-authoring history if another author's commits are mixed in.
Quick Start
Step 1: Create a Project Folder
mkdir reshape-commits && cd reshape-commits
Step 2: Download the Template
Click Download above, then:
mv ~/Downloads/CLAUDE.md ./
Step 3: Clean Up a Branch
claude
Ask Claude to clean up the commits on your current feature branch before you open (or update) a PR. It will read the base and the full diff, propose a numbered regrouping for your approval, then reset and re-commit — never force-pushing without --force-with-lease and never touching main.
Tips & Best Practices
- Always let it show the proposed final commit list before executing — a one-line rationale per group makes it easy to catch a wrong split (e.g., a refactor accidentally bundled with a behavior change) before it's baked into history.
- If your project has a
CONTRIBUTING.mdwith commit-message conventions (type prefixes, scope names, subject rules), point to it — the reshaping should match the house style rather than invent its own. git reset --softplus staged re-commits is deliberately preferred over interactive rebase here: no editor to drive, no pick/squash lines to get wrong, and conflicts only ever show up once, at the final push.
Limitations
- Rewrites history — only ever safe on a feature branch that hasn't been merged and that no one else is actively building on top of; the guardrails refuse
mainand already-merged branches, but a shared feature branch with other active contributors still needs care. - Refuses to touch commits authored by someone else without asking first — on a branch with mixed authorship, expect it to stop and check rather than silently reshape everyone's history.
- Assumes a single target base branch (typically
main); a more complex branching model (stacked PRs, multiple integration branches) needs the base identified manually before the flow starts.