Below is my git commit history:
HEAD
... +500 commits
A 4140759b
A c5cf69a2
A 3e5282cb ⎯┐ << Merge branch B
| 94936548 B
| 02a550ce B
A 5d09daa9 ⎯┤ << Pull request
| afbe397b B << Merge branch A into B
| 74fe4f3c B
| 86cdc993 B
| 223e1740 B
| a7ea596a B
| 0d4c36cf B
A 2740d295 |
A 24437962 |
A 73725f04 |
A 90be4300 |
A 6b1720d6 ⎯┘
A d65bf4bd
...
I want to remove B branch history and merge commit, and leave A branch history only.
But, they are very old commits, with hundreds of commits between the latest commits,
so git rebase -i
command makes a lot of conflicts that I couldn't solve.
It doesn't matter if a few commits, between d65bf4bd and c5cf69a2, dropped.
However, recent commits, after c5cf69a2, should not be affected.
How can I completely remove B branch history, from history?
My expected result looks like this:
HEAD
... +500 commits
pick A 4140759b
pick A c5cf69a2
[drop] A 3e5282cb ⎯┐ << Merge branch B
[drop] | 94936548 B
[drop] | 02a550ce B
[drop] A 5d09daa9 ⎯┤ << Pull request
[drop] | afbe397b B << Merge branch A into B
[drop] | 74fe4f3c B
[drop] | 86cdc993 B
[drop] | 223e1740 B
[drop] | a7ea596a B
[drop] | 0d4c36cf B
pick A 2740d295 |
pick A 24437962 |
pick A 73725f04 |
pick A 90be4300 |
pick A 6b1720d6 ⎯┘
pick A d65bf4bd
...
Here is one way to squash together the history of branch B:
git replace
to create a commit, with the same end content but only one parent, and a replacement rulegit replace --graft [target commit] [the parent you want]
# with the hashes you provided:
git replace --graft 3e5282cb 2740d295
on your machine, git log --oneline --graph
should already display a simplified history
git filter-repo
or git filter-branch
git filter-repo --replace-refs delete-no-add
# or
git filter-branch --env-filter true
a note about git filter-branch
: making the replacement permanent is actually a side effect of git filter-branch [any command]
, you can use any subcommand (--index-filter
, --env-filter
, --tree-filter
...) and any scripted action as long as it makes git filter-branch
go through. --env-filter true
happens to be convenient, because git
will not read or write any file on disk, and true
has no side effects.