1

If I have the following history

A-B-C-D-E-F-G

A is root commit and I want to squash A-D, but keep E unchanged, I found a way to do it in 2 steps

git rebase --onto A C

then it becomes

A-D'-E-F-G

then I do a

git rebase -i --root

and in vim I interactively set D' to be s, then I can get what I want

A'-E-F-G

which A' has all the changes from A-B-C-D, while E is still the original E( its diff does not change)

Can I do above in a simpler way ? could it be done in some magic --onto command in one git command ? ( non interactively) Because in the real example, I have a few hundred of commits instead of just A-B-C-D here.

Shuman
  • 3,914
  • 8
  • 42
  • 65

2 Answers2

1

I got this answered not too long ago (like a couple of weeks ago?). It can be done like this:

git checkout --orphan a-new-branch D
git commit -m "Single commit for A..D"
git cherry-pick D..G

And you have it right there. There are other ways doing resets and stuff but I think that's simple enough.

Update: If the history after D is complex, it might be better to run a rebase for the last step:

git rebase --rebase-merges D G --onto a-new-branch

And if that history is complex and it includes merges with conflicts, I can offer this script to take care of that last step to avoid having to redo the merges with conflicts:

https://github.com/eantoranz/git-replay

eftshift0
  • 26,375
  • 3
  • 36
  • 60
  • But I have to cherry pick F G too, what if I have a few hundred commits there instead of just E F G? I have a feeling another git rebase --onto can do it. Ah thanks did not know cherry pick can do ranges. – Shuman Mar 17 '23 at 08:10
  • I had adjusted it a couple of minutes ago. – eftshift0 Mar 17 '23 at 08:11
0

Assuming all that you've written works as-is. Could you use the commit right before A for your command?

X-A-B-C-D-E-F-G

Given what you say, using

git rebase --onto X C

should give you

X-D'-E-F-G

unixia
  • 4,102
  • 1
  • 19
  • 23