I am trying to use git replace
to rewrite history and replace the tree of a
commit with the tree object of a different commit. I want to make this
permanent.
The documentation for git replace
seems to indicate this is
possible. I adapted the following recipe for replacing a commit from How to
prepend the past to a git repository?.
# setup a second branch with a different tree
# existing repo which already contains a few commits
git checkout master -b master2
echo "test file" > testfile.txt # a different tree
git add testfile.txt
git commit -m "test"
# save the SHA1 of the original tree for later reference
ORIG=$(git rev-parse master^{tree})
# replace the tree of master with the one from master2
git replace master^{tree} master2^{tree}
# verify the contents of the replaced tree
git ls-tree master
this works, master's tree has been replaced by the one from master2, including the extra file:
100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad readme.txt
100644 blob 16b14f5da9e2fcd6f3f38cc9e584cef2f3c90ebe testfile.txt
However, trying to make this permanent, fails:
git filter-branch --tag-name-filter cat -- --all
yields following reply from git:
Rewrite e7619af3e5d424a144845c164b284875c4c20c7a (2/2)
WARNING: Ref 'refs/heads/master' is unchanged
WARNING: Ref 'refs/heads/master2' is unchanged
error: Object bc705106db90164b2e688b4b190d4358f8b09a56 is a tree, not a commit
error: Object bc705106db90164b2e688b4b190d4358f8b09a56 is a tree, not a commit
fatal: ambiguous argument 'refs/replace/e7a75e980c7adc0d5ab1c49ecff082b518bb6cf8^0':
unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
WARNING: Ref 'refs/replace/e7a75e980c7adc0d5ab1c49ecff082b518bb6cf8' is unchanged
and after I remove the replace reference, master gets its original tree back:
git replace -d ${ORIG}
git ls-tree master
3b18e512dba79e4c8300dd08aeb37f8e728b8dad readme.txt
Why does git filter-branch
complain about the replacement and how do I do make
the replacement of the tree permanent?
P.S. I know I can do this with a filter-branch --tree-filter
or grafts, but
(how) can I do it with git replace
?