My personal favorite is using git reset --soft
.
So, say you want to squash from HEAD~1000
up to this point (HEAD~1000
being the last surviving commit that won't be squashed):
git reset --soft HEAD~1000
git commit -m "Squashed a lot of stuff"
That's it. You can use a revision ID instead of using HEAD~n
references.
I see that you want to do it like by segments.... so, say.... let's squash HEAD~400 to HEAD~200... then from HEAD~200 to HEAD~100... then from HEAD~100 to HEAD. So, let's create a temp branch where we will do our work.
git checkout -b temp HEAD~200
git reset --soft HEAD~400
git commit -m "squashing first segment"
# next segment
git checkout the-original-branch~100
git reset --soft temp
git commit -m "Second segment"
git branch -f temp #set temp over here
# final segment
git checkout --detach the-original-branch
git reset --soft temp
git commit -m "Final segment"
git branch -f temp #set temp over here
# if you like the result, feel free to move whatever branch over here
git branch -f whatever-branch
# and delete temp if so you want
git branch -D temp
Very easy, I think.
After one day, I just realized (by answering another question) that it can be done in a much simpler way:
git branch -f temp $( git commit-tree -p HEAD~400 -m "first squash" HEAD~200^{tree} )
# that set up temp on the first squash
git branch -f temp $( git commit-tree -p temp -m "second squash" HEAD~100^{tree} )
# temp has move to second squash
git branch -f temp $( git commit-tree -p temp -m "final squash" HEAD^{tree} )
Now temp has the squashed commits the way it was requested in my example. Feel free to do a reset --hard
over there (the usual warning when using reset --hard
).