Had to do this a few months ago for the totally vanity reason of hiding an exposed email address embedded in a bunch of commits which for some reason google's search engine was now picking up. Grrr...
Anyhow... in the process I learned a bit about how rebasing worked, and wrote these notes for my future self and anyone else it might help!
Remember that the following steps basically rewrite history! Therefore always begin by creating a new branch for any rebasing activities.
git checkout -b <branchname>. OK? Also, If anything goes pear-shaped and you need to restart,
git rebase -–abort is your best friend. Ready? Here goes:
git rebase –i <parent-sha>
...where the parent-sha is the commit prior to the commit you want to modify. The
-i means interactive. This command basically opens up your default editor (eg vi/vim)... and you change the 'pick' string to 'edit' for the commits that you wish to alter, then save and quit (eg for vi editor,
Interactively fix any conflicts that arise. This usually involves:
git add ...to stage a file that was added historically, or
After everything is cleaned up, do
git rebase --continue. Tadaaa!!! You're done.
Remember you can always do
git rebase -–abort to just back the hell out of everything and try again!
In this case, you provide both:
git rebase –i --root <root-sha> <latest-sha>
I found this link very helpful. In this case, you basically:
git reflogor visually browse to your first ever commit in github/gitlab whatever)... and then
git checkout –b <brch>
git checkout <root-sha>
Make whatever edits you like to the commit, e.g.:
git commit --amend --author "blahblah"
Then, based on answers I found in StackOverflow, this is what worked for me:
git rebase --onto HEAD HEAD master
WARNING: This obviously messes with your MASTER branch... hope you noticed.
UPDATE: Actually, it appears you can tack on whatever branch has modifications you want to apply, not just HEAD. But if you run it as above, it actually modifies master and you will find yourself back in the master branch!! In my case, that's what I wanted. Magic!!
Next, push this new source tree back up to your remote:
git push origin master --force
Explanation: If you've just rebased right from the root, then natch all the commit SHAs will now be different and github will deem your remote master irreconcilable with your local, recently-messed-with master... hence the
Side note on merging branches with unrelated histories: When tree of SHAs differ, github will not let you do a PR and merge because now master and (for example) the rebased branch have entirely different histories. I found another answer on SO that deals with I guess the general case of all these scenarios. Haven't had to try this yet (tho, give it time! lol), but the swiss-army-knife, "just do what I tell you to do" command seems to be:
git merge –s ours master –allow-unrelated-histories
This forces a merge even though the 2 branches now have unrelated histories, using the "ours" strategy (-s) in which things in our current branch trumps whatever's in the other branch.)
Well that's all I have on this topic, folks! I hope it helps someone out there! :o)