How can I insert extra commits using git replace?

57 Views Asked by At

What I'm trying to do is add one or more extra commits in between two other historical commits. I could do this with git rebase however this only works in simple cases - it is completely unpractical for large or complex repos (as any conflicts have to be re-resolved). Hence I'm forced to used git replace in this case.

Given this repo:

$ git log --all --graph --oneline
* 7c12005 (HEAD -> rewrite) commit 1_edit
| * 5d3e705 (master) commit 5
| * 662f654 commit 4
| * 9d45a4e commit 3
| * e374cd1 commit 2
|/  
* a054d47 commit 1

To reproduce it:

git init 
for i in {1..5}; do
  echo $i > "$i.txt"
  git add "$i.txt"
  git commit -m "commit $i"
done

git checkout -b rewrite HEAD~4

i="1_edit"
echo $i > "$i.txt"
git add "$i.txt"
git commit -m "commit $i"

I now want to move commit 2,3,4,5 ontop of 7c12005. I could accomplish this with:

git checkout master
git rebase rewrite

However how do I do something similar with git replace? When I tried that with git replace --graft -f master~4 rewrite I get this weird result:

$ git log --oneline master
5d3e705 (HEAD -> master) commit 5
662f654 commit 4
9d45a4e commit 3
e374cd1 commit 2
a054d47 (replaced) commit 1
7c12005 (rewrite) commit 1_edit

I find it weird because I expect it to go:

...
commit 3
commit 2
commit 1_edit
commit 1

Even stranger (commit 1 and commit 1_edit vanishes) is if I add --graph:

git log --oneline --graph master 
 * b4595ea (master) commit 5
 * ccdf08c commit 4
 * e6272c3 commit 3
 * 81e6eb7 commit 2
1

There are 1 best solutions below

2
Chris Stryczynski On

I needed to do git replace --graft -f master~3 rewrite instead where master~3 is commit 2. In other words the command would replace commit 2 with another commit 2 but which had a different parent.

I don't understand the logic or operation when master~4 (commit 1) is referenced instead. I would think it would replace commit 1 (which is root - no parent), with commit 1 edit (which has 1 parent). I think this might be a bug or edge case.