Git filter-branch refuses to run because backup refs from a previous operation already exist. You can either force overwrite the backup with -f flag or manually delete the refs/original namespace.
This error occurs when you run `git filter-branch` on a repository that has already undergone a filter-branch operation. Git's filter-branch command automatically creates backup references under `refs/original/` before rewriting history, allowing you to recover if something goes wrong. When filter-branch detects existing backup refs, it stops to prevent accidentally overwriting your safety net. This is a protective measure, not a fatal error - Git is asking you to explicitly confirm that you want to proceed. The backup refs contain pointers to your original commit history before the rewrite. Once you verify that your previous filter-branch operation completed successfully and you no longer need the backup, you can safely proceed with the new operation.
The simplest solution is to add the -f (force) flag to your filter-branch command. This tells Git to remove the existing backup and create a new one:
git filter-branch -f --tree-filter 'your-filter-here' HEADOr for other filter types:
git filter-branch -f --env-filter 'your-filter-here' -- --allWarning: Using -f will delete your existing backup refs. Make sure you don't need them before proceeding.
If you want to explicitly remove the backup refs before running filter-branch again, use this command:
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdinThis safely removes all refs under refs/original/ using Git's own reference management. Alternatively, you can delete them one by one:
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -dAfter removing the refs, run your filter-branch command normally.
If the git commands don't work (for example, if refs are corrupted), you can delete the backup directory directly:
rm -rf .git/refs/originalImportant: If you've run git gc, the refs might be packed. Check and edit .git/packed-refs to remove any lines starting with refs/original/:
# View packed refs containing 'original'
grep refs/original .git/packed-refs
# If found, edit the file and remove those lines
# Then run garbage collection
git gc --prune=nowAfter your filter-branch operation succeeds and you've verified the results, perform a complete cleanup to reclaim disk space:
# Remove backup refs
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
# Expire all reflogs immediately
git reflog expire --expire=now --all
# Run aggressive garbage collection
git gc --aggressive --prune=nowThis removes all traces of the old history and can significantly reduce repository size, especially if you removed large files.
Confirm that all backup refs have been removed:
# Should return nothing
git for-each-ref refs/original/
# Check the directory doesn't exist
ls .git/refs/original/
# Verify packed-refs has no original entries
grep refs/original .git/packed-refsIf all commands return empty or "not found," you can safely run filter-branch again.
## Consider Migrating to git-filter-repo
The Git project now recommends using git-filter-repo instead of git filter-branch. The newer tool offers several advantages:
- Performance: Orders of magnitude faster than filter-branch, especially on large repositories
- Safety: Better handling of edge cases and fewer silent corruption risks
- Simplicity: More intuitive command syntax for common operations
- No backup conflicts: Uses a different mechanism that avoids the refs/original issue
### Installation
# Using pip
pip install git-filter-repo
# Or download directly
curl https://raw.githubusercontent.com/newren/git-filter-repo/main/git-filter-repo > git-filter-repo
chmod +x git-filter-repo### Converting filter-branch commands
The git-filter-repo project provides documentation for converting filter-branch commands. For example:
# Old filter-branch way
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
# New filter-repo way
git filter-repo --path passwords.txt --invert-paths### Using filter-lamely for compatibility
If you have scripts that rely on filter-branch syntax, filter-lamely provides a drop-in replacement that uses filter-repo under the hood:
# Instead of:
git filter-branch -f --tree-filter 'rm -f secret.txt' HEAD
# Use:
filter-lamely --tree-filter 'rm -f secret.txt' HEAD## Recovering from a bad filter-branch
If you need to undo a filter-branch operation, the backup refs are your lifeline:
# Restore master branch to its original state
git checkout refs/original/refs/heads/master -B master
# Or reset to the backup
git reset --hard refs/original/refs/heads/masterThis is why Git is cautious about overwriting backup refs - they're your only way to recover if the rewrite goes wrong.
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git