commit-reorder

star 0

Organize changes into logical, atomic commits. Works with both staged/unstaged changes (no commits yet) and existing commits ahead of base. Use when the user asks to clean up commits, reorder commits, squash and reorganize, or prepare a branch for PR review.

relight14 By relight14 schedule Updated 2/20/2026

name: commit-reorder description: Organize changes into logical, atomic commits. Works with both staged/unstaged changes (no commits yet) and existing commits ahead of base. Use when the user asks to clean up commits, reorder commits, squash and reorganize, or prepare a branch for PR review.

Git Commit Reorder

Split N messy commits into M logical, atomic ones while preserving the exact same final diff.

Safety Rules

  1. ALWAYS create a backup branch first — never reorder on the original branch
  2. ALWAYS save the full diff as a patch before any reset
  3. ALWAYS verify the final diff matches the original after reordering
  4. ALWAYS present the commit plan to the user before executing
  5. Run build/lint after each commit if the project has these commands

Process

Phase 1: Setup and backup

# Save current branch name
ORIGINAL_BRANCH=$(git branch --show-current)

# Detect base branch (main, master, dev, develop, trunk — whichever exists)
BASE_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo "main")

# Detect mode: are there commits ahead of base, or only staged/unstaged changes?
COMMIT_COUNT=$(git rev-list --count ${BASE_BRANCH}..HEAD 2>/dev/null || echo "0")
HAS_STAGED=$(git diff --cached --quiet 2>/dev/null; echo $?)    # 1 = has staged changes
HAS_UNSTAGED=$(git diff --quiet 2>/dev/null; echo $?)           # 1 = has unstaged changes

Mode A: No commits ahead (COMMIT_COUNT == 0 and HAS_STAGED == 1 or HAS_UNSTAGED == 1) Changes exist only in the working tree / staging area. No backup branch needed since there are no commits to lose — the working tree IS the backup.

# Save the full diff (staged + unstaged combined) as backup
git diff HEAD > /tmp/full-unstaged.patch
git diff --cached > /tmp/full-staged.patch

# Unstage everything so we start clean
git reset HEAD

Mode B: Commits ahead of base (COMMIT_COUNT > 0) The current flow — reorder existing commits.

# Create backup branch
git branch "${ORIGINAL_BRANCH}-backup"

# Create clean working branch
git checkout -b "${ORIGINAL_BRANCH}-reorder"

# Save full diff as backup
git diff ${BASE_BRANCH}..HEAD > /tmp/full.patch

Phase 2: Analyze changes

Mode A (no commits):

# List all changed files (staged + unstaged)
git status --porcelain | awk '{print $2}'

# Get stats overview
git diff HEAD --stat

Mode B (commits ahead):

# List all commits
git log --oneline ${BASE_BRANCH}..HEAD

# List all changed files
git diff ${BASE_BRANCH}..HEAD --name-only

# Get stats overview
git diff ${BASE_BRANCH}..HEAD --stat

For each changed file, determine: does this file belong to exactly one commit?

Answer Action
Yes Stage directly with git add in the right commit
No (mixed changes) Needs intermediate versions using write/stage/restore pattern
Entire file rewritten Include in the commit where the primary change lives

Phase 3: Plan commit groups

Categorize each file into a logical group:

Group Examples Commit prefix
Infrastructure / plumbing IPC handlers, preload, types, config feat: or refactor:
i18n / translations locale JSON files feat(i18n):
UI / components React components, CSS feat(ui):
Services / business logic services, stores, orchestrators feat: or fix:
Tests test files, mocks test:
Build / CI workflows, scripts, package.json ci: or build:
Docs README, CLAUDE.md docs:

Order commits inside-out:

  1. Infrastructure / config / types
  2. Services / business logic
  3. i18n / translations
  4. UI / components + styles
  5. Tests
  6. Build / CI
  7. Docs

STOP HERE. Present the plan to the user as a table:

Proposed commits:
1. refactor: extract video types to shared module
   - src/types/video.ts, src/types/index.ts
2. feat: add chapter service with API integration
   - src/lib/api.ts, src/hooks/useVideoData.ts
3. feat(ui): add chapters panel component
   - src/components/ChaptersPanel.tsx, src/index.css
...

Ask: "Does this grouping look right? Want to move any files between commits?"

Phase 4: Execute reorder

Only after user approval:

Mode A (no commits): Changes are already unstaged from Phase 1. Skip reset.

Mode B (commits ahead):

# Reset all commits but keep changes in working tree
git reset --soft ${BASE_BRANCH} && git reset HEAD

Both modes — create the planned commits:

# For each planned commit:
git add <files-for-this-commit>
git commit -m "<type>(<scope>): <description>"

Handling files with mixed changes (intermediate versions)

When a file has changes belonging to multiple commits:

cp file.ts /tmp/file-final.ts          # 1. Save final version
# Edit file to contain only this commit's changes
git add file.ts                         # 2. Stage intermediate version
cp /tmp/file-final.ts file.ts           # 3. Restore final version on disk

To build the intermediate version, use git show ${BASE_BRANCH}:<filepath> to get the original and apply only the subset of changes for the current commit.

Lock files

Lock files (bun.lock, package-lock.json, etc.) cannot have intermediate versions. Include them in whichever commit adds the most dependencies.

Renames and deletions

git add -u packages/old-name/     # Stage deletions of tracked files
git add packages/new-name/        # Stage new files
# Git auto-detects renames when both are staged together

Phase 5: Verify

# Compare diffs — must be identical
git diff ${BASE_BRANCH}..HEAD > /tmp/new.patch
diff /tmp/full.patch /tmp/new.patch

# Show final commit list
git log --oneline ${BASE_BRANCH}..HEAD

For Mode A, compare against the combined staged+unstaged patch saved in Phase 1.

If the diff comparison is NOT empty, something went wrong.

Mode A recovery: Changes are still in the working tree. Re-stage with git add -A. Mode B recovery: Restore from backup:

git checkout "${ORIGINAL_BRANCH}"
git branch -D "${ORIGINAL_BRANCH}-reorder"

Phase 6: Optional build verification

If the project has build/lint commands, verify each commit compiles:

git log --oneline ${BASE_BRANCH}..HEAD --reverse | while read hash msg; do
  git checkout $hash
  npm run build 2>/dev/null || echo "⚠️ Build fails at: $msg"
done
git checkout "${ORIGINAL_BRANCH}-reorder"

This is optional but recommended — broken intermediate commits make bisecting harder later.

Phase 7: Present results

Show the user:

  • 📋 Old commits vs new commits (side by side)
  • ✅ Diff verification result
  • ⚠️ Any build warnings per commit

Ask:

  • "Want me to replace the original branch with these clean commits?"
  • If yes: git checkout ${ORIGINAL_BRANCH} && git reset --hard ${ORIGINAL_BRANCH}-reorder
  • Clean up: git branch -D ${ORIGINAL_BRANCH}-backup ${ORIGINAL_BRANCH}-reorder

Commit message format

<type>(<scope>): <short description>

<body: what changed and why, 2-4 lines>

Rules:

  • Subject line: imperative mood, max 72 chars
  • Body: explain what and why, not how
  • One logical change per commit

Useful commands reference

Command Purpose
git diff ${BASE_BRANCH}..HEAD > patch Save full diff as backup
git diff ${BASE_BRANCH}..HEAD --stat Overview of all changes
git diff ${BASE_BRANCH}..HEAD --name-only List changed files only
git show ${BASE_BRANCH}:<path> See original file version
git diff --cached --name-status Verify staged files before commit
git add -u <dir> Stage deletions of tracked files
git status --porcelain Machine-readable status check
Install via CLI
npx skills add https://github.com/relight14/TownHall --skill commit-reorder
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator