How to fix a git rebase on a public master branch
What is Git Rebase
git rebase is a command in Git that allows you to modify the commit history of a branch by moving or combining a sequence of commits to a new base commit, so that all the new commits in the feature branch will be together after the updated master branch where the feature branch branched out from.
This is usually the case when you are working on a feature branch, then there are some hotfixes in the master branch, which the feature branch should be built on top of.
To rebase onto the master branch, simply run
git rebase master while you are on the feature branch. Or if you are using an IDE like IntelliJ, you can simply right click the branch you want to rebase onto, then select
rebase 'feature' onto 'master'.
However, there’s a certain pitfall to that. The Golden Rule of Rebasing is to never use it on public branches. As in the marble diagram above, there are no issues if
C have not been pushed to the remote. The final outcome will still follow the sequence
C after pushing and merging to master.
C have already been pushed to remote, i.e.
C are commits that you can see in your online repository (e.g. github, gitlab, bitbucket), the git rebase will make
C in your local to become
C2. Meaning the changes are the same, but they will have different commit hashes. Do remember that this only happens in your local, so it is still just
C in your remote.
When you do a
git status, git will identify that you doesn’t have
C, but you have new commits
C2. So if you try to do a
git push, it will not allow you to do so, but ask you to do a
git pull first. And the result of doing that will be like in the diagram below, now you have all
C2, which are duplicates. The
M2 are just the merge commits to show that merging was performed.
This is not what we want, as the history will not be clean.
Then what can I do if this already happened? Unfortunately, the only way is to rewrite history if you want clean commits. It does not matter much if you are the only one working on the feature branch. It’s your history, you can rewrite it the way you need. Furthermore, the feature branch is going to be deleted after merging to the master.
So we use
git reset to reset our local history to the commit just before we do the rebase. And to find the commit, we use
git reflog, which gives us a list of all the actions we have performed.
As in the screenshot above, we find the commit just before the merge
f9b337f, which is
d99d47e, and we do
git reset --merge d99d47e. Thus we are rewriting our local history to just before we did the
git pull, after the
Now, instead of
git pull, you can just force the history change in the remote with
git push --force. If unfortunately someone is also working on the same feature branch, just get them to stash their uncommitted changes and pull the changes.
If you already did more commits in the feature branch after the git pull (which is after M in the diagram titled
After Pulling), you still can execute the same method above. After the reset, you can still use
git reflog to get the hashes of all previous commits you have done. So you can cherry-pick the commits into your now altered history before you do a force push.