In the previous post we took a look at the basics of
git rebase The most important part we will take a deeper look in this part: The history will be re-written. As mentioned in the previous post, this is not necessarily a bad thing. To have a greater view, we need more repositories. We could also do it in one, but that would be an aweful overact. The figure shows three repositories. One of them being the bare remote and two clones of that. They are all on the same state, the repostiory we left off in the first part.
Avoiding “merge bubbles”
Let’s see what a
merge bubble is. A very easy way to create one, is using
git pull --no-ff every time. You will create merge commits that may have been avoided.
As you can see, both merge commits
9fbfced may have been avoided. You can push and pull this way infinitely without introducing any changes to your repository, isn’t that great? Let’s see, how
git rebase is a very handy tool here. There are many merges that can be “fast-forwarded”, which means they can be applied without creating a
merge commit. As the previous figure shows, the latest merge commit
9fbfced has not been pushed to the remote repository. The previous post mentions:
You cannot push to a remote branch which
HEADwas already on a commit that has been re-written by the
We are not at that point, so we are good to go in re-writing history. But, let’s make this a bit more realistic by having the other repository pushed other changes, too.
Using rebase prior pushing changes
The second repository has pushed its changes to the remote. When the first one tries this, the push will be rejected. This happens because the most recent commit of it does not have the remotes
HEAD in its tree. Namingly, it means
341c62e is not a commit that has
c7878a6 as a (grand-)ancestor. What could we do about this? Correct, we could
git pull to retrieve the current tree from the origin. What do you think will happen here? A new merge commit will be added. The two commits to be merged are the
HEAD commits of both cloned repositories -
Now that we have done this, it’s not getting better. The keyword is
rebase, who would have guessed? Since the first repository didn’t push its changes by now. We are still good to rebase and push afterwards. We only need to know the most recent commit of the remote repository. We have pulled its state, so we already know it, it’s
c7878a6. However you can issue
git show origin/master --oneline to see the most recent commit your local repository is aware of the remote. In order to update its knowledge, issue
git fetch origin after that you can be sure about the result of
git rebase c7878a6 all goes well, our unnecessary merge commit
004fc7a is not part of our branch anymore. Now we are good to push our changes to the remote repository! The push won’t be rejected, everything goes well. Successful rebase without breaking anything!