Local-only object aliasing. Niche, occasionally lifesaving.
git replace lets you swap one object for another at lookup time, without rewriting history. It's the surgical alternative to filter-branch.
A replacement is a local-only redirect stored in refs/replace/<sha>. When Git looks up <sha>, it transparently returns the replacement instead. Original objects stay; SHAs don't change.
git replace [-f] <object> <replacement>
git replace --edit [-f] <object>
git replace --graft <commit> [<parent>...]
git replace --convert-graft-file
git replace -d <object>...
git replace -l [<pattern>]| Flag | What it does |
|---|---|
--edit | Open the object in your editor; the edited result becomes the replacement. Best UX for fixing one bad commit message in deep history. |
--graft <c> [<p>...] | Rewrite a commit's parents only. The killer feature: stitch a shallow clone to historical archive. |
--convert-graft-file | Migrate the legacy .git/info/grafts file (deprecated) into proper replace refs. |
-l / --list | List existing replacements, optionally matching a glob. |
-d / --delete | Remove a replacement, restoring the original lookup. |
-f / --force | ⚠️ Overwrite an existing replacement without complaining. Easy to clobber a teammate's grafts on a shared repo. |
--raw | On --edit, present the raw object bytes instead of the parsed form. |
git replace --edit deadbeefgit replace --graft HEAD~5 abc1234git replace --convert-graft-filegit replace -lgit replace -d deadbeef.git/info/grafts file to a supported mechanism.git replace --graft 1a2b3c4 deadbeef cafef00dgit replace --edit 1a2b3c4git replace -lgit replace -d 1a2b3c4--graft when joining histories; it's the cleanest way to bridge a --depth=1 clone with a legacy archive.git push origin 'refs/replace/*' if you want collaborators to see them — they don't propagate by default.refs/replace/*.git replace -l when debugging weird history.Hit each option, then Check answers. Score is recorded; Next is always open.