What is Git Rebase?
Git rebase organizes branching paths and makes the repository structure linear. It allows you to patch changes onto your origin or master branch.
In December of 2011, Evan Coury posted an article on his now-defunct blog (original link is a 404) titled “A simple explanation of git-rebase,” and his Twitter post still comes up in searches. I really like this post for its clarity. In Evan’s own words:
…this post was mostly meant to help you feel confident that you really understand what it is that git-rebase is doing, why git-push won’t work properly after a rebase if you’ve already pushed any of the rebased commits, and most importantly, how to avoid one of the most common problems I’ve seen with people using git-rebase…
Its main virtue is that it does a great job of explaining the concept without over-complicating it. It’s not a how-to. It’s specifically written to help people who are already trying to learn git-rebase understand the concept. I’ve sent out a link to it in the Internet Archive to people learning git-rebase plenty of times already, so I thought I’d republish it here, and hopefully give it a new life until and unless Evan decides to bring back blog.evan.pro. What follows is taken verbatim from the original post:
Posted by Evan Coury on December 2, 2011
git-rebase without actually understanding what it does can cause headaches for you and the developers you’re working with. I don’t like headaches, so let’s take a minute to review what exactly
master is at commit
C, and you create a branch
feature/my-topic. So you have two branches pointed at the same commit like this:
feature/my-topic / A---B---C master
Next, you make two commits
feature/my-topic and push it to your origin (we’ll say GitHub):
D---E feature/my-topic / A---B---C master
Meanwhile, let’s say master also gets two commits,
D---E feature/my-topic / A---B---C---D'---E' master
So now you want to rebase your
feature/my-topic branch onto
master, so you run
git rebase master. The result is this:
F---G feature/my-topic / A---B---C---D'---E' master
The key here is to recognize that commits
feature/my-topic no longer exist, and have been re-written as
G respectively, with master’s HEAD (
E') as the new base. This means that some history has been re-written. Because of this, if you were to try running
git push origin feature/my-topic, you would be greeted with a non-fast-forward error. Instead, if you really need to push the rebased branch up to your origin, you’ll need to run
git push -f (see note below).
DO NOT PULL, MERGE, OR REBASE FROM
origin/feature/my-topic AT THIS POINT!!!
Why not? Because Git simply thinks, “Oh look,
origin/feature/my-topic has two commits (
E) that we don’t have here locally in
feature/my-topic. Let’s merge them in!”… That’s a problem though, because we do have those commits, but their hashes were re-written to
G when we ran
So what would happen if you actually did merge? Your history would look something like this mess:
D---E---X---F--G feature/my-topic / A---B---C---D'---E' master
In the above result,
D is a duplicate of
E is a duplicate of
X is a useless merge commit gluing the whole mess together. Using
git-rebase may avoid the merge commit, but you’ll still have those pesky duplicates, so you’re no better off.
NOTE: If there are other developers deriving work from your
feature/my-topic branch that is pushed; you must be careful about performing a
git push -f, as it can cause problems for those other developers. Also,
git push -f can be a somewhat destructive operation if used carelessly. In the context I described, it should be pretty safe, but unless you have a specific reason, it’s generally better to just leave it to the person merging your pull request to perform the rebase locally on their end. This results in
master being able to simply fast-forward to the new commit (guaranteed no merge conflicts when merging into
master) and no re-written history is forcefully pushed to any public repositories.
If you have any questions, feel free to ask in a comment below or contact our team directly.