skills/tidy-branch/SKILL.md
Interactively clean up the current branch's commits (squash fixups, reword sloppy messages, reorder, drop) before merging — especially important on repos using rebase-merge where every branch commit lands on main verbatim
npx skillsauth add stevenmburns/dot-claude-files tidy-branchInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Review the commits on the current branch (those that would land on main via rebase-merge or PR) and help the user collapse, reword, reorder, or drop them into a clean, review-ready sequence. Works by proposing a rebase plan, getting user approval, and then executing a non-interactive git rebase -i with a scripted todo-list.
When to use this: before /merge-pr on a repo configured for rebase-merge (where messy commits pollute main directly, not just the PR diff). Also useful before /create-pr if the in-progress branch has accumulated "wip", "fix typo", or "address review" commits that should be collapsed into their logical parents.
When NOT to use this: if the branch has already been merged; if you're on main or another protected branch; if the commits are already clean (one tidy commit per logical change).
Check preconditions. Run git branch --show-current. If the branch is main or master, stop and report — this skill is for feature branches only. Run git status — if the working tree is dirty, stop and report (commit or stash first; rebase on a dirty tree is a mess).
Run lint and fix. Run the project's linter on the entire repo (the same scope CI checks — typically ruff check --fix and ruff format for Python projects; check pyproject.toml or CI config for the exact commands and paths). If the linter produces changes, stage and commit them with a style: ruff fix message (including the Co-Authored-By trailer). This ensures lint fixes are captured as a commit before the rebase plan is built, so they can be squashed into their logical parent during tidying. If the linter finds unfixable errors, stop and report.
Determine the base. Find what the branch diverges from. Usually this is main, but check with git merge-base HEAD main and confirm the base commit exists. Use the output of git log main..HEAD --oneline to list the candidate commits.
Check push state. Run git log @{u}..HEAD --oneline and git log HEAD..@{u} --oneline (the second may fail if no upstream — that's fine). Record whether the branch has an upstream and whether the local/remote have diverged. This determines whether step 7 needs a force-push.
Analyze the commits. For each commit in git log main..HEAD --oneline:
git log main..HEAD --format=fullergit log main..HEAD --statPropose a plan and get approval. Write a clear plan as a markdown table or list, showing: original commit order, proposed action (pick/squash/fixup/reword/drop/reorder), and for reword/squash cases the proposed new message. Present it to the user and wait for explicit approval before executing. This is a destructive history rewrite — confirmation is required, not optional. If the user wants changes to the plan, revise and re-present.
Execute the plan. Once approved:
<action> <short-sha> <subject>, where action is one of pick, squash, fixup, reword, edit, drop).GIT_SEQUENCE_EDITOR="cp /tmp/tidy-todo.txt" \
GIT_EDITOR="<msg-editor-script>" \
git rebase -i <base-sha>
where <msg-editor-script> is a small shell script the skill writes that checks the commit being edited and substitutes the appropriate pre-written message. For the common case of a single squash with a known final message, a simpler pattern is GIT_EDITOR='cp /tmp/new-msg.txt' git rebase -i <base>.git rebase --continue manually or abort.Verify the result. After rebase completes, show git log main..HEAD --oneline so the user can see the new tidy history. Run git log main..HEAD --stat briefly to confirm file counts and that no content was dropped unexpectedly. If the rebase changed the diff relative to main (it shouldn't unless drop was used), flag this explicitly.
Force-push if needed. If the branch had an upstream and the history rewrite diverged it:
git push --force-with-lease (never plain --force) to update the remote branch. --force-with-lease refuses to push if someone else has pushed to the branch since the last fetch, which protects collaborators.git push -u origin <branch> when ready."main and HEAD — commits older than the merge base are never touched.--force-with-lease, not --force. This is non-negotiable even on solo repos, because the cost of a mistake is lost work.git status output.main, never run it on commits older than the merge base, and always get explicit plan approval before executing.tools
Scan open GitHub issues, flag duplicates, and summarize with suggested priorities
tools
Analyze the changes in the current PR and suggest a more accurate title if the current one no longer fits
data-ai
Merge the open PR for the current branch into main, delete the branch, and pull main
development
Clone the current repo into a sibling directory with a fresh Python venv