How to fix fatal: replace ref 'refs/replace/abc1234' already exists in Git

GitINTERMEDIATELOWUpdated Dec 6, 2025ยท 121 views

The 'replace ref already exists' error occurs when you try to create a git replace reference for an object that already has one. Use the --force flag to overwrite, or delete the existing replacement first.

Quick fix

Fixes fatal: replace ref 'refs/replace/abc1234' already exists

# List all replacement references
git replace -l

# Or use more detailed format
git replace --list

# Show the refs directly
git for-each-ref refs/replace/
  1. List existing replacement references
  2. Use the --force flag to overwrite the existing replacement
  3. Delete the existing replacement first
  4. Handle replacements from filter-repo or filter-branch
git โ€” error
# List all replacement references
git replace -l
# Or use more detailed format
git replace --list
# Show the refs directly
git for-each-ref refs/replace/
fatal: replace ref 'refs/replace/abc1234' already exists

What this error means

This error occurs when you attempt to create a replacement reference for a Git object, but a replacement for that object already exists. Git's replace mechanism allows you to substitute one object (typically a commit) with another without rewriting history, making it useful for correcting mistakes or hiding sensitive data. When you run `git replace <object> <replacement>`, Git creates a reference under `refs/replace/<object-hash>`. If this reference already exists because you (or someone else) previously created a replacement for that same object, Git refuses to overwrite it by default. This safety measure prevents accidental loss of existing replacements. The replace mechanism is a powerful but somewhat advanced feature. Unlike rebasing or amending, replacements don't actually modify the object store - they just tell Git to transparently swap one object for another whenever the original is accessed. This makes replacements reversible and non-destructive.

Typical symptoms

  • Git replace command fails with 'replace ref already exists' message
  • Cannot update an existing replacement to point to a different object
  • Error appears when trying to graft commits with git replace --graft
  • Replace operation fails after fetching replacements from a remote
  • Cannot create replacement after running git filter-repo or filter-branch

Common causes

  1. A replacement reference already exists for the specified object
  2. Previously ran git replace on the same commit without removing it
  3. Fetched replacement refs from a remote repository that conflict with local ones
  4. Used git filter-repo or filter-branch which created replacement refs
  5. Attempting to modify a replacement without using the --force flag

How to fix "fatal: replace ref 'refs/replace/abc1234' already exists"

1List existing replacement references

Before making changes, check what replacement references currently exist:

bash
# List all replacement references
git replace -l

# Or use more detailed format
git replace --list

# Show the refs directly
git for-each-ref refs/replace/

This shows all objects that have replacements defined. The output displays the hash of each replaced object.

To see what a specific replacement maps to:

bash
# Show details of a specific replacement
git replace -l <object-hash>

# View the replacement ref directly
git show-ref refs/replace/<object-hash>
2Use the --force flag to overwrite the existing replacement

If you want to update an existing replacement to point to a different object, use the -f or --force flag:

bash
# Overwrite existing replacement
git replace -f <object> <new-replacement>

# Example: Replace commit abc1234 with commit def5678
git replace -f abc1234 def5678

This will overwrite the existing replacement reference without needing to delete it first.

With git replace --graft:

bash
# Force a graft replacement
git replace --graft -f <commit> <new-parent1> [<new-parent2>...]

# Example: Graft commit to have no parents (make it a root commit)
git replace --graft -f abc1234

The force flag is useful when you've refined your replacement and want to update it without the extra step of deletion.

3Delete the existing replacement first

If you prefer to remove the old replacement before creating a new one, use the -d flag:

bash
# Delete a specific replacement
git replace -d <object>

# Example
git replace -d abc1234

# Then create the new replacement
git replace abc1234 def5678

To delete multiple or all replacements:

bash
# Delete all replacements (be careful!)
git replace -d $(git replace -l)

# Or delete refs directly
git for-each-ref --format='delete %(refname)' refs/replace/ | git update-ref --stdin

Deleting the replacement restores Git's view of the original object - nothing is lost, the replacement mapping is simply removed.

4Handle replacements from filter-repo or filter-branch

If replacement refs were created by git filter-repo or git filter-branch, you may want to clean them up:

After git filter-repo:

bash
# filter-repo has an option to handle replacements
git filter-repo --replace-refs delete-no-add

# Or delete the replacement refs manually
git for-each-ref --format='delete %(refname)' refs/replace/ | git update-ref --stdin

After git filter-branch:

bash
# filter-branch creates backup refs in refs/original/
# but may also create replacement refs

# Check for replacement refs
git for-each-ref refs/replace/

# Delete them if no longer needed
git for-each-ref --format='delete %(refname)' refs/replace/ | git update-ref --stdin

Note: Only delete replacement refs if you're sure you no longer need the mapping between old and new objects.

5Push or fetch replacement refs from remotes

Replacement refs are local by default and require explicit pushing/fetching:

To push replacements to a remote:

bash
# Push all replacement refs
git push origin 'refs/replace/*:refs/replace/*'

# Force push (overwrite remote replacements)
git push origin '+refs/replace/*:refs/replace/*'

The + prefix forces the push, which is needed if the remote already has conflicting replacement refs.

To fetch replacements from a remote:

bash
# Fetch all replacement refs
git fetch origin 'refs/replace/*:refs/replace/*'

# Force fetch (overwrite local replacements)
git fetch origin '+refs/replace/*:refs/replace/*'

Configure automatic fetching:

bash
# Add to fetch refspec in .git/config
git config --add remote.origin.fetch '+refs/replace/*:refs/replace/*'

When fetching causes conflicts (same object has different replacements locally and remotely), you'll get the "already exists" error unless you use the + prefix to force.

Advanced notes

### Understanding Git Replace

The git replace command creates a reference in refs/replace/<sha1> that points to the replacement object. Whenever Git encounters the original object, it transparently substitutes the replacement:

bash
# How Git stores replacements
.git/refs/replace/abc1234...  -> contains hash of replacement object

This mechanism is used internally by tools like git filter-repo to map old commits to new ones.

### Disabling Replacements Temporarily

You can disable replacement lookups with an environment variable:

bash
# Run a command ignoring all replacements
GIT_NO_REPLACE_OBJECTS=1 git log

# Or use --no-replace-objects flag
git --no-replace-objects log

This is useful for debugging or seeing the original unmodified history.

### Making Replacements Permanent

If you want to bake replacements into the actual commit graph (so replacements are no longer needed), use git filter-repo:

bash
# Make all replacements permanent by rewriting history
git filter-repo --replace-refs delete-and-add

# The replacement refs will be removed after history is rewritten

Warning: This rewrites history and will change commit hashes.

### Types of Replacements

Git replace can work with different object types:

bash
# Replace a commit with another commit
git replace <commit-sha> <replacement-commit>

# Replace a tree (directory structure)
git replace <tree-sha> <replacement-tree>

# Graft: change a commit's parents
git replace --graft <commit> [<new-parent>...]

# Edit a commit (opens editor)
git replace --edit <commit>

### Replacement Refs in Bare Repositories

In bare repositories (like those on servers), replacement refs work the same way but are more commonly inherited from clones or pushes:

bash
# On the server, you may need to explicitly enable replace ref fetching
git config receive.advertisePushOptions true

### Troubleshooting Replace Conflicts

If you're seeing "already exists" errors after collaborating with others:

1. Check who created which replacements: git log -g refs/replace/
2. Decide whether to keep local or remote replacements
3. Use + prefix when fetching/pushing to force your version

Be careful when forcing - you might lose someone else's intentional replacement.

Frequently asked questions

What does "fatal: replace ref 'refs/replace/abc1234' already exists" mean?
This error occurs when you attempt to create a replacement reference for a Git object, but a replacement for that object already exists. Git's replace mechanism allows you to substitute one object (typically a commit) with another without rewriting history, making it useful for correcting mistakes or hiding sensitive data. When you run git replace <object> <replacement>, Git creates a reference under refs/replace/<object-hash>.
How do I fix "fatal: replace ref 'refs/replace/abc1234' already exists"?
The 'replace ref already exists' error occurs when you try to create a git replace reference for an object that already has one. Use the --force flag to overwrite, or delete the existing replacement first.
What causes "fatal: replace ref 'refs/replace/abc1234' already exists"?
A replacement reference already exists for the specified object Previously ran git replace on the same commit without removing it Fetched replacement refs from a remote repository that conflict with local ones
Is the "fatal: replace ref 'refs/replace/abc1234' already exists" error serious?
It is a low-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading