git-replace
Replace Git objects for history rewriting
TLDR
Replace any commit with a different one, leaving other commits unchanged
Delete existing replace refs for the given objects
Edit an object's content interactively
SYNOPSIS
git replace [-f] <object> <replacement>
git replace -d <object>
git replace --list [<pattern>]
PARAMETERS
<object>
The SHA-1 hash or symbolic name of the Git object that you want to replace.
<replacement>
The SHA-1 hash or symbolic name of the Git object that will take the place of the original <object>.
-f, --force
If a replacement for the specified <object> already exists, force Git to create a new replacement, overwriting the old one.
-d, --delete
Delete an existing replacement for the specified <object>. This restores the visibility of the original object.
--list
List all existing replacements. If a <pattern> is provided, it filters the list to show only replacements whose original object matches the pattern.
<pattern>
An optional regular expression pattern used with --list to filter the displayed replacements based on the SHA-1 of the original object.
DESCRIPTION
The git replace command allows users to transparently substitute one Git object (commit, tree, blob, or tag) with another. This powerful feature is primarily used for non-destructively correcting history, testing changes, or temporarily masking problematic objects without rewriting the original Git history. When a replacement is created, Git operations that traverse the object database (such as git log, git blame, or git show) will see the replacement object instead of the original one. The original object remains in the repository, and the replacement is stored as a special reference under refs/replace/.
This mechanism is particularly useful for fixing issues like bad commits that may contain sensitive data or large files, without forcing a history rewrite on shared repositories, as the replacements are local by default. However, it's crucial to understand that replacements are not automatically propagated by standard git push or git fetch operations, requiring explicit handling for sharing.
CAVEATS
Replacements are stored as loose references under refs/replace/ and are not part of Git's packed objects, which can slightly affect performance for very large numbers of replacements.
They are not automatically transferred during typical git push or git fetch operations. To share replacements, you must explicitly push them using commands like git push --all or git push --mirror, which includes `refs/replace/` references.
Replacements only affect object traversal. The original objects remain in the repository and are still accessible directly by their SHA-1. While useful for temporary fixes or local testing, replacements do not permanently alter the commit history. To make changes permanent and remove the original objects, tools like git filter-repo or git filter-branch are typically used after confirming the replacement.
<B>STORAGE MECHANISM</B>
Replacements are stored as ordinary Git references in a special namespace: refs/replace/<SHA-1-of-original-object>. The content of this reference is the SHA-1 of the replacement object. This decentralized storage allows for easy creation and deletion of replacements.
<B>ENVIRONMENT VARIABLE</B>
The base directory for replacement references can be overridden by setting the GIT_REPLACE_REF_BASE environment variable. By default, it is refs/replace/. This can be useful for advanced or custom Git setups.
HISTORY
The git replace functionality was introduced early in Git's development to provide a robust way to modify how Git traverses the object graph without resorting to destructive history rewriting. This addresses scenarios where a user might want to correct a problematic commit (e.g., one containing sensitive information or an erroneously large file) without forcing a history rewrite for all collaborators. It acts as a lightweight, non-destructive overlay, offering a flexible alternative to more aggressive history-rewriting tools for certain use cases. Its core mechanism of using refs/replace/ has remained a stable and integral part of Git.
SEE ALSO
git-filter-repo(1), git-filter-branch(1), git-log(1), git-show-ref(1)