Rebase as an Alternative to Merge

How can I use "rebase" to integrate changes? What's the difference between merge and rebase?

Rebase as an Alternative to Merge

Today, we’ll look at “Rebase” - an alternative way to integrate changes. Just like Merge, a Rebase also integrates changes from one branch into another. It is neither better nor worse than merge - it’s just an alternative tool.

Before we talk in detail about Rebase, let’s take another look at Merge.

When Git performs a merge, it looks for three commits:

  • the common ancestor of both branches (at this point in time, both branches had the same content and then evolved differently)
  • and the endpoints of each branch

Combining these three commits is what merge does.

In very simple cases, one of the two branches doesn’t have any new commits since the branching happened. Its latest commit is still the common ancestor.

In this case, performing the integration is really simple: Git can just add all the commits of the other branch on top of the common ancestor commit. In Git, this simplest form of integration is called a “fast-forward” merge. Both branches then share the exact same history.

In a lot of cases, however, both branches moved forward individually.

For the integration, Git will have to create a new commit that contains the differences between them - the merge commit. A merge commit gets automatically generated by Git. It’s like a knot or a junction that connects two branches.

When you later want to understand what happened, you’ll have to look at the history of BOTH branches. Because the merge commit itself will most likely be NOT very meaningful.

Now, some people prefer to go without such automatic merge commits. Instead, they want the project’s history to look as if it had evolved in a single, straight line. No indication remains that it had been split into multiple branches at any point.

Let’s walk through a rebase operation step by step. We want to integrate the changes from "branch-B" into "branch-A" - but now by using rebase.

First, Git will kind of “undo” all new commits on "branch-A". However, of course, it won’t discard them: you can think of them as being “saved away temporarily”.

Then, from "branch-B", it applies the commits that we want to integrate. At this point, both branches look exactly the same.

In the final step, the new commits on "branch-A" are now re-applied - but on a new position, on top of the integrated commits from "branch-B". They are, indeed, re-based.

The result looks like development had happened in a straight line. The original commit structure was preserved - instead of a merge commit that contains all the combined changes.

Rebase is a nice alternative to merge - but you always have to keep one thing in mind: Rebase rewrites history!

In the diagram, you can see that commit C3 has an asterisk symbol. That’s because it’s a different commit - although it has the same contents as the original commit. The reason is that it now has a new parent commit: C4, which it was rebased onto. This is enough to make it a new commit with a new hash ID.

Rewriting history in such a way is no problem under one condition: if it only affects commits that haven’t been published, yet. If you’re instead rewriting commits that have already been pushed to a public server, you’re in trouble: because another developer has probably already based his work on the original C3 commit. This makes it indispensable for other newer commits.

Therefore, you should use rebase only for cleaning up your local work - but never to rebase commits that have already been published.

Effectively performing a rebase in Tower is really simple.

  • First - just like with merge - you should make sure you’re on the correct branch. The one that shall receive the new commits.
  • Then, simply click the “Rebase” button in the toolbar - and select the branch you want to integrate. Alternatively, you can also drag the branch you want to integrate, hold the option key, and drop it onto your current HEAD branch.

One last hint before we finish this video: you can use rebase also when performing a pull. This is because pull not only downloads changes, but also directly integrates them. By default, pull does this by using merge. However, you can also use rebase instead. In Tower, this is a simple option in the “Pull” dialog.

That’s it for now. Thanks for watching!