The target commit may have parents and descendants.
it needs to replace the old commit in place,
so it\'s not as simple as cherry
c
Okay, let's see if this helps.
WARNING:
Are you sure you want to do this? Scroll down if yes.
This is called graft point. You create a file .git/info/grafts
and have the following info:
<commit-id> <new-parent-of-the-commit>
Let's say you have this:
/---D
A---B---C
Now you want to replace B
with D
(without changing the commit id), you put this in graft:
<commit-id-of-C> <commit-id-of-D>
It keeps the old commitid
, with the limitation stated above.
I'm not familiar with Git but in Mercurial, you can do this: Pop the latest commit from the repository and save it in a "patch" (hg qimport
). The result is the repo without any trace of the latest commit plus a patch that would give you the starting state.
So the recipe would be to pop stuff from the repo until the commit to modify becomes HEAD. Pop that, too, modify the patch (or apply the patch without commit and modify the workspace).
Now you can commit the new version and apply all the other patches.
Since Git and Mercurial are very similar, there is probably a Git command to achieve the same but I don't know its name. Maybe this answer can help: https://serverfault.com/questions/12373/how-do-i-edit-gits-history-to-correct-an-incorrect-email-address-name
No, you can't do that.
The point of SHA-1 is to prevent changes like these. The whole git architecture depends on the assumption that SHA-1 uniquely identify the object in all git repository. No way to workaround this (not without redesigning everything, that is).
The details are explained in the Git Magic book.