This would do it (call the branch you are on originalBranch):
git switch --det c2
git switch -c temp
git reset --soft c1
git commit -msquash
git rebase --onto temp c2 originalBranch
git branch -D temp
The idea is this:
- We get ourselves back at
c2 and plant a branch name temp there, so that we can find it again.
- We then squash from
c2 all the way back to c1 inclusive — that's the soft reset followed by a commit; this is a type 1 regret. The name temp now points to this new single squash commit.
- Finally, we return to whatever was the original HEAD (which I have named
originalBranch) and move all the commits starting at (but not including) the old c2 onto the new single squash commit, which (as I have already said) is pointed to by the name temp.
- Our work is now done, but we no longer need the branch name
temp for anything, so we delete it.
So we have now gone from this:
A -- B -- C1 -- ? -- ? -- C2 -- D -- E -- F <- originalBranch
To this:
A -- B -- C1 -- squash -- D' -- E' -- F' <- originalBranch
\
-- ? -- ? -- C2 -- D -- E -- F
The old commits, as you can see from my diagram, still exist, but they will all be mopped up during the next garbage collection because no name points to them any longer.