There are several reasons why you may need completely refactor your working branch. The most common one is that you stumbled upon some things you fixed along your way resolving an issue. Your branch will grow over time until you are finished. Now you want to submit your code. You have to split it up into digestible pieces and maybe have to rewrite some WIP commits you made. Luckily we are using git! With git you can do it with a few commands with a safety belt on!
This wiki page helped me a lot to come up with my solution. But my case wasn't in there so I decided to write this post.
I wanted to squash different commits into each other then cherry pick the commits into new branches, to unsquash them there into several new nicely written commits.
To do that I figured out the following steps.
You have to get the hash of the commit your branch is based on:
git merge-base <yourBranch> <basedUponThisBranch>
Use rebase with the hash from the first step, to be able to amend all commits in your branch:
git rebase -i $hash
Squash your desired commits, maybe save your commit messages in some place if it was useful. Now change squash the commits you wanted to squash.
After you squashed everything you want to cherry pick the commits into different branches:
git checkout -b <newBranch> upstream/master
Cherry pick the squashed commit you need from $yourBranch. Therefore you need it's hash. Look through the commits of $yourBranch to find your commit:
git log $yourBranch
Note the hash of the commit you want to cherry pick, than do:
git cherry-pick $hash
Now you've copied the commit from $yourBranch to $newBranch. To enable a save net while unsquashing the commit you can use rebase again:
git rebase -i HEAD~1
Change "pick" to "edit". After that reset the committed changes:
git reset HEAD~
Add portions from your changes to make multiple commits, by using:
git add -p
Commit ;) and replay step 9 and 10 until no changes are left.
When you have committed all your changes you run the following command to finalize the rebasing step. If something went wrong before you can run git rebase --abort to abort the steps you took:
git rebase --continue
Redo step 4 to 11 for every squashed commit you want to have in a separate branch. It sounds like a lot of work but it's not that hard.
Have fun using git :)