Git rebase solves the same problem as git merge. Both git merge and rebase are used to integrate changes from one branch into another branch – they just do it in different ways; and it’s important to know the difference.
Let’s think of a scenario.
Our master branch (m) have commit: 1 -> 2 -> 3. Now we need to develop a feature. So we created our own feature branch (f) from the master branch with the latest commit no: 3. We are working on our feature and pushed 3 commits no: 5, 7 and 9. In the meantime; master branch remains busy and commit 4, 6 and 8 was pushed by our amazing team members.
Now at some point; we might need to do 2 things:
- Your feature development is finished and you need to push your work (commit 5,7 & 9) of feature branch (f) to master branch (f);
- Bring the things that has been pushed to master branch (m) (commit 4,6 & 8) into your own branch (f), and then continue to work on the branch (f).
Consider the first scenario. And let’s consider ‘merge’ route. That is we go to master branch and merge the feature branch with the master with the commands –
git checkout master git merge feature
By merging feature into master, master obtains a new commit — a ‘merge commit’. This commit contains everything from our commit – (5+7+9) – into a combined sort of commit (10*) and it appends itself after commit 8 on master.
Now let’s consider the second scenario. And this time we will go with ‘rebase’ route. We will bring all the magical commits pushed into master (m) into our branch (f). Keep in mind; the current commit history for our branch is: 1-> 2-> 3-> 5-> 7-> 9. Now we rebase with master with the following command –
git checkout feature git rebase master
Now this part is interesting. Rebase moves the base of our branch. The process is this –
- First it brings all the commits from master (1-> 2-> 3-> 4-> 6-> 8)
- And applies our commits (5-> 7-> 9); after this base commit 8; one by one to create (5′ -> 7′ -> 9′)
So the new history for our branch (f) becomes – 1-> 2-> 3-> 4-> 6-> 8 -> 5′-> 7′-> 9′. It does not create a new all-in-one sorts of commit; rather it rewrites the history of the branch. Note that; commit 5,7,9 is same as 5′,7’9′ to us but git treats them as new commits (with new SHA’s).
Now here comes the tricky part.
Say our good friend Rafi is working on the same feature. He checked out the feature branch after we pushed the commit 5; and he has committed 10 & 11. So; his commit history looks like this –
1-> 2-> 3-> 5-> 10 -> 11.
In the meantime; we changed the history of feature branch to –
1-> 2-> 3-> 4-> 6-> 8 -> 5′-> 7′-> 9′.
Now whether Rafi wants to bring back master branch commit into his own copy of feature branch; update his copy of feature branch with our feature branch or push his commit into the master branch; there is potential for some conflict and issues; and all because git rebase rewrote the history of the feature branch unlike merge.
So; golden rule of thumb of using rebase is –
don’t rebase a branch unless you are the only one who are using it.
If we want to control and alter commits as they are moved to the new branch while rebasing; we can use Interactive Rebasing. The command for this is –
git checkout feature git rebase -i master
This will open a text editor listing all of the commits that are about to be moved. Here the listing defines what the branch will look like after the rebase is performed. By changing the pick command and/or re-ordering the entries, we can make the branch’s history look like whatever we want.
For example, if the 2nd commit fixes a small problem in the 1st commit, we can condense them into a single commit with the fixup command. Eliminating insignificant commits like this makes feature’s history much easier to understand. This is a benefit of rebase that git merge simply cannot do.
Pros of merge –
- Simple and familiar
- Preserves complete history and chronological order
- Maintains the context of the branch
Cons of merge –
- Commit history can become polluted by lots of merge commits
- Debugging using git bisect can become harder
Pros of Rebase –
- Streamlines a potentially complex history
- Manipulating a single commit is easy
- Avoids merge commit “noise” in busy repository with busy branches
- Cleans intermediate commits by condensing them into a single commit
Cons of rebase –
- Squashing the feature down to a handful of commits can hide many important details.
- Rebasing public repositories can be dangerous when working as a team.
- It’s more work using rebase to keep our feature branch updated always.
- Rebasing with remote branches sometimes requires force push which may cause problems if not done properly.
Git Merge and Rebase: Summary
Create a feature branch and then –
- ALWAYS rebase from master to the branch. (merge is fine too)
- And merge from the branch back to master. (avoid rebasing).