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-configFiles
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)
Attribution
Comments (0)
No comments yet. Be the first to comment!
