Rewrites git history to permanently remove sensitive data. DESTRUCTIVE OPERATION - rewrites commit history...
Permanently removes sensitive data from git history using git-filter-repo. This is a DESTRUCTIVE operation that rewrites commit history.
This skill:
/repo-security-purge
"purge secrets from git history"
"remove sensitive data from history"
"clean the git history"
Check if installed:
git-filter-repo --version
If not installed:
# macOS
brew install git-filter-repo
# pip
pip install git-filter-repo
# Linux
apt install git-filter-repo # or package manager equivalent
git-filter-repo works best on a fresh clone:
git clone --mirror <repo-url> repo-mirror
cd repo-mirror
# Check git-filter-repo is installed
git-filter-repo --version
# Check we're in a git repo
git rev-parse --is-inside-work-tree
# Check for uncommitted changes
git status --porcelain
If uncommitted changes exist: Stop and ask user to commit or stash first.
If git-filter-repo not installed: Provide installation instructions and stop.
This skill depends on /repo-security-scan --history for findings. Check for an existing scan:
# Look for today's scan report
ls -t security/*-scan.md 2>/dev/null | head -1
If recent scan exists (today):
If no recent scan OR history not scanned:
/repo-security-scan --historyRead the scan report and extract items marked as "History" or "HISTORY":
From scan report, extract:
- Files to remove (marked as History - e.g., "certs/server.key (HISTORY)")
- Patterns to scrub (secrets found in history)
- Commit references where secrets were introduced
Build a purge list from the report's history findings.
If no history findings:
No secrets found in git history.
Current file issues (if any) can be fixed with /repo-security-clean.
Nothing to purge from history.
Exit gracefully.
Build a list of:
Files to remove entirely:
.pem, .key).env, credentials.json).p12, .pfx)Patterns to scrub from content:
Present findings:
Secrets found in git history:
Files to remove:
- certs/server.key (added in abc123, 15 commits ago)
- config/.env (added in def456, 42 commits ago)
- secrets/credentials.json (removed in ghi789, but still in history)
Patterns to scrub:
- API key "sk-abc123..." found in 3 commits
- Password "hunter2" found in 2 commits
Display prominent warning:
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ļø DESTRUCTIVE OPERATION ā ļø ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā£
ā ā
ā You are about to REWRITE GIT HISTORY. ā
ā ā
ā This will: ā
ā ⢠Change ALL commit hashes in the repository ā
ā ⢠Break existing clones, forks, and pull requests ā
ā ⢠Require FORCE PUSH to update remote ā
ā ⢠Be IRREVERSIBLE after force push ā
ā ā
ā Items to purge: ā
ā ⢠3 files (certs/server.key, config/.env, ...) ā
ā ⢠2 secret patterns ā
ā ā
ā Affected: ā
ā ⢠847 commits will be rewritten ā
ā ⢠All branches and tags ā
ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Do not proceed with a simple yes/no. Require the user to type a specific phrase:
To proceed, type exactly: PURGE HISTORY
> _
Only continue if input matches exactly PURGE HISTORY.
If user types anything else, abort:
Aborted. No changes made.
To clean secrets without rewriting history, use /repo-security-clean instead.
Before purging, create a backup:
# Create a backup branch/tag
git tag backup-before-purge-$(date +%Y%m%d)
# Or create full backup
git clone --mirror . ../repo-backup-$(date +%Y%m%d)
Inform user:
Backup created: ../repo-backup-20260118
If something goes wrong, you can restore from this backup.
# Remove specific files from all history
git-filter-repo --invert-paths --path certs/server.key --path config/.env
# Remove by pattern
git-filter-repo --invert-paths --path-glob '*.pem' --path-glob '*.key'
Create a replacements file (replacements.txt):
sk-abc123def456ghi789jkl012mno345pqr678==>[REDACTED_API_KEY]
hunter2==>[REDACTED_PASSWORD]
mongodb://user:pass@host:27017/db==>mongodb://[REDACTED]@host:27017/db
Apply replacements:
git-filter-repo --replace-text replacements.txt
# Remove files larger than 10MB from history
git-filter-repo --strip-blobs-bigger-than 10M
# Verify secrets are gone
git log -p --all | grep -E "(sk-abc123|hunter2)" || echo "ā Secrets removed"
# Check file is gone from all history
git log --all --full-history -- certs/server.key || echo "ā File purged"
# Run security scan again
# (invoke /repo-security-scan --history)
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā HISTORY REWRITTEN ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Purged from history:
ā certs/server.key
ā config/.env
ā secrets/credentials.json
ā 2 secret patterns scrubbed
Backup location: ../repo-backup-20260118
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ļø REQUIRED NEXT STEPS:
1. ROTATE ALL EXPOSED CREDENTIALS
The secrets were public. Assume they are compromised.
- [ ] Rotate API key sk-abc123...
- [ ] Change password for database
- [ ] Revoke and regenerate any tokens
2. FORCE PUSH TO REMOTE
ā ļø This will break existing clones and forks!
git push --force --all origin
git push --force --tags origin
3. NOTIFY COLLABORATORS
All team members must re-clone or run:
git fetch origin
git reset --hard origin/master
4. UPDATE FORKS (if applicable)
Fork owners need to sync with upstream.
5. CLEAN UP BACKUPS
After verifying everything works:
rm -rf ../repo-backup-20260118
git tag -d backup-before-purge-20260118
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Report saved: security/YYYYMMDD-purge.md
Write to security/YYYYMMDD-purge.md:
# Security Purge Report
**Repository:** <repo-name>
**Date:** YYYY-MM-DD HH:MM
**Operation:** Git history rewrite
## ā ļø Destructive Operation Completed
This report documents a git history rewrite operation.
## Items Purged
### Files Removed from History
| File | Originally Added | Commits Affected |
|------|------------------|------------------|
| certs/server.key | abc1234 | 15 |
| config/.env | def5678 | 42 |
| secrets/credentials.json | ghi9012 | 8 |
### Patterns Scrubbed
| Pattern | Replacement | Occurrences |
|---------|-------------|-------------|
| sk-abc123... | [REDACTED_API_KEY] | 3 |
| hunter2 | [REDACTED_PASSWORD] | 2 |
## Statistics
- Commits rewritten: 847
- Branches affected: 5
- Tags affected: 12
## Backup
Location: `../repo-backup-20260118`
## Required Actions
- [ ] Rotate all exposed credentials
- [ ] Force push to remote
- [ ] Notify collaborators
- [ ] Clean up backup after verification
## Verification
```bash
# Verify purge was successful
git log -p --all | grep "sk-abc123" # Should return nothing
## Error Handling
| Error | Resolution |
|-------|------------|
| git-filter-repo not installed | Provide installation instructions |
| Uncommitted changes | Ask user to commit or stash |
| Not a git repository | Abort with message |
| Protected branch on remote | Warn about force push restrictions |
| Confirmation not matched | Abort, no changes made |
## Alternatives
If history rewrite is too disruptive:
1. **Accept the exposure** ā rotate credentials, add to .gitignore going forward
2. **Create fresh repo** ā copy current files to new repo, lose history
3. **Use BFG Repo-Cleaner** ā alternative tool, similar results
## Safety Notes
- This skill will **NEVER** force push automatically
- This skill will **NEVER** proceed without explicit typed confirmation
- This skill will **ALWAYS** create a backup first
- This skill will **ALWAYS** warn about collaborator impact