git-rewrite-history

MatiasComercio's avatarfrom MatiasComercio

Rewrites git history safely with dry-run-first workflow. Supports commit amending, squashing, rewording, tag updates, and force pushing. Always proposes plan before execution. Triggers on keywords: rewrite history, squash commits, amend commit, fix commit, update tags, rebase history, clean history, fix tag

⭐16stars🔀1forks📁View on GitHub🕐Updated Jan 3, 2026

When & Why to Use This Skill

The Git Rewrite History skill provides a secure, dry-run-first framework for modifying repository history. It automates complex Git operations like squashing commits, rewording messages, and updating tags while enforcing strict safety protocols—including mandatory backups and explicit user approval—to prevent accidental data loss during force pushes and rebases.

Use Cases

  • Case 1: Cleaning up a messy development branch by squashing multiple incremental commits into a single, logical commit before merging a Pull Request.
  • Case 2: Correcting typos, updating commit messages, or amending file contents in historical commits to maintain a professional and accurate project timeline.
  • Case 3: Managing repository tags after a rebase to ensure version markers point to the correct new commit hashes across local and remote environments.
  • Case 4: Safely performing bulk branch deletions and history rewrites with a guided risk assessment and backup branch creation for easy rollback.
namegit-rewrite-history
descriptionRewrites git history safely with dry-run-first workflow. Supports commit amending, squashing, rewording, tag updates, and force pushing. Always proposes plan before execution. Triggers on keywords: rewrite history, squash commits, amend commit, fix commit, update tags, rebase history, clean history, fix tag
project-agnostictrue

Git Rewrite History

Safely rewrite git history with mandatory dry-run planning and user confirmation.

Critical Rules

  1. ALWAYS DRY RUN FIRST - Propose plan, never execute without approval
  2. ALWAYS WAIT FOR CONFIRMATION - User must explicitly approve before destructive operations
  3. ALWAYS CREATE BACKUP - Backup branch before any rebase/amend
  4. ALWAYS SAVE TAG MESSAGES - Preserve tag annotations before deletion

Supported Operations

Operation Use Case
Amend Content Change files in historical commits
Squash Commits Combine multiple commits into one
Reword Message Change commit message text
Update Tags Move tags to new commits after rebase
Delete Branches Remove local and remote branches
Force Push Push rewritten history to remote

Workflow

Phase 1: ANALYZE

Gather current state before proposing changes.

# Current branch and HEAD
git rev-parse --abbrev-ref HEAD
git rev-parse --short HEAD

# Commit history
git log --oneline --decorate main

# All tags
git tag -l

# All branches
git branch -a -v

Phase 2: PLAN (DRY RUN)

OUTPUT FORMAT:

## DRY RUN - PROPOSED PLAN

### Current State
- Branch: {branch}
- HEAD: {sha}
- Commits: {count}
- Tags: {list}

### Operations
1. {operation description}
2. {operation description}
...

### Commands to Execute
{numbered list of exact commands}

### Risk Assessment
| Risk | Impact | Mitigation |
|------|--------|------------|

### Affected
- Commits: {list}
- Tags: {list}
- Remote: {yes/no force push required}

**Awaiting approval to proceed.**

Phase 3: CONFIRM

STOP AND WAIT for user to respond with approval (e.g., "OK", "proceed", "yes").

Phase 4: BACKUP

# Create backup branch
git branch backup/pre-rewrite-$(date +%Y%m%d-%H%M%S) HEAD

# Save tag messages to temp files
git tag -l --format='%(contents)' {tag} > /tmp/{tag}-message.txt

Phase 5: EXECUTE

Pattern A: Amend Content in Historical Commit

# Save cleaned file
cp {file} /tmp/cleaned-file

# Stash if needed
git stash

# Start interactive rebase (mark target as "edit")
GIT_SEQUENCE_EDITOR="sed -i '' 's/^pick {short_sha}/edit {short_sha}/'" git rebase -i {parent_sha}

# Apply changes when stopped
cp /tmp/cleaned-file {file}
git add {file}
git commit --amend --no-edit

# Continue
git rebase --continue

Pattern B: Squash N Commits into 1

# For commits 2-N, change "pick" to "squash"
GIT_SEQUENCE_EDITOR="sed -i '' '2,{N}s/^pick/squash/'" git rebase -i --root
# OR for non-root:
GIT_SEQUENCE_EDITOR="sed -i '' '2,{N}s/^pick/squash/'" git rebase -i {parent_sha}

# When prompted for message, use edit mode:
GIT_SEQUENCE_EDITOR="sed -i '' '1s/^pick/edit/'" git rebase -i --root
git commit --amend -m "{new_message}"
git rebase --continue

Pattern C: Reword Commit Message

# Mark commit for edit
GIT_SEQUENCE_EDITOR="sed -i '' 's/^pick {short_sha}/edit {short_sha}/'" git rebase -i {parent_sha}

# Amend message
git commit --amend -m "{new_message}"

# Continue
git rebase --continue

Pattern D: Delete Branches

# Local branches
git branch -D {branch1} {branch2}

# Remote branches
git push origin --delete {branch1} {branch2}

Phase 6: UPDATE TAGS

After any rebase, commit hashes change. Tags must be recreated.

# Get new commit hashes
git log --oneline -{N} main

# Delete old tags (local)
git tag -d {tag1} {tag2}

# Recreate tags on new commits
git tag -a {tag} {new_sha} -F /tmp/{tag}-message.txt
# OR with inline message:
git tag -a {tag} {new_sha} -m "{message}"

Phase 7: FORCE PUSH

# Delete remote tags first
git push origin :refs/tags/{tag1} :refs/tags/{tag2}

# Force push branch
git push --force-with-lease origin {branch}

# Push new tags
git push origin {tag1} {tag2}

Phase 8: VERIFY

# Final history
git log --oneline --decorate -{N} main

# Commit count
git rev-list --count main

# Tags
git tag -l | sort -V

# Remote sync
git status

Output Format

After completion, report:

## Complete

### Final State
{commit} (tag: {tag}) {message}
{commit} (tag: {tag}) {message}
...

### Summary
| Metric | Before | After |
|--------|--------|-------|
| Commits | {N} | {M} |
| Tags | {list} | {list} |

### Verification
| Check | Result |
|-------|--------|
| Commit count | {N} |
| Tags exist | {list} |
| Remote synced | Yes/No |

Safety Notes

  • --force-with-lease prevents overwriting others' work
  • Backup branches preserve original state for rollback
  • Tag messages saved to /tmp allow recreation with original annotations
  • Reflog preserves history locally (expires after 90 days by default)