Back to skills

Git Rewrite History

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

3 stars
0 votes
0 copies
0 views
Added 12/19/2025
data-aibashgit

Install via CLI

$openskills install MatiasComercio/agentic-config
Download Zip
Files
SKILL.md
---
name: git-rewrite-history
description: 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
project-agnostic: true
allowed-tools:
  - Bash
  - Read
  - Edit
  - Write
---

# 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.

```bash
# 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:**

```markdown
## 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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.

```bash
# 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

```bash
# 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

```bash
# 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:

```markdown
## 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)

Comments (0)

No comments yet. Be the first to comment!