Lessons in Git: merge/rebase

Lessons in Git: merge/rebase

The distributed version control system called Git has changed the way developers think of code merging and branching, compared to the previous version control systems like CVS and SVN.

With Git, these operations became relatively easy and fast to do. This system allows developers to create new features isolated from the master branch and integrate them at a later point when the feature is ready for integration.

If you are new to Git, the following links should help get you started quickly:

In Git, there are two main ways to integrate changes from one branch into another:

  1. merge
  2. rebase

We will look at merging with the -ff option and the –no-ff option. Note: there is no git –no-ff rebase command.

A Quick Demo Setup

Before we look at the two ways of Git merging, let’s first set up a working Git repository with the following commands:

Let’s now create a new branch named “myfeature” and switch to it:

Now we can make a change to the “foo.txt” file in the “myfeature” branch of our local repo:

Let’s assume our “myfeature” change is complete, and now we would like to integrate this feature into our “master” branch.

Our git graph would look like this:

As stated before about Git, we have two ways to go about this: either doing a merge or a rebase.

How to Use: git merge

The git merge command joins two or more branches together.

First, let’s switch back to the “master,” so that we can apply the merge on our main branch.

We can now do the merging, but let’s first discuss the two different ways to create a merge.

Often the current branch head is an ancestor of the named commit (“myfeature”). This is the most common case. In this scenario, a new commit is not needed to store the combined history. Instead, the git HEAD (along with the index) is updated to point at the named commit without creating an extra merge commit.

The default behavior of git merge is to do a a fast-forward merge when possible. This default behavior can be made explicit with the -ff option, or this behavior can be suppressed with the no-fast-forward merge (–no-ff) option. When merging an annotated tag, Git always creates a merge commit even if a fast-forward merge is possible.

When using –no-ff, someone reviewing the git history can clearly see the branch you checked out to work on. Also, note how the –no-ff merge has an extra merge commit at the end.

Below is an image that shows the difference between a –no-ff and -ff merge.

git --no-ff rebase

So you now have the option of using either:

After this command, our git graph would look like this:

Or we could keep the branch history by doing:

In this latter case, our git graph would now look like this:

And if we execute the following git log command:

This will show a similar git graph:

Which type of merge you prefer depends on how much of the branch information you want to store when you do a merge.

How to Use: git rebase

The second way of integrating changes from one branch into another is to do a git rebase.

When merging brings two branches together while preserving the graph of each commit history, rebasing unifies the branches by rewriting changes from the source branch so they appear as children of the destination branch.

The git rebase forward-ports local commits to the updated upstream head. Rebasing is the process of moving a branch to a new base commit.

This is what that looks like in a git graph. Assume the following history exists and the current branch is “myfeature”:

And if we now do:

The result would be:

The “master” branch now contains the “myfeature” branch changes at commit “G” without creating a merge commit. So instead of joining the branches with a merge commit, rebasing integrates the “myfeature” branch by building on top of master. The result is a linear history that may be easier to understand for developers. The git log would now show the linear history of “D—E—F—G master”.

In case of conflict, git rebase will stop at the first problematic commit and leave conflict markers in the tree.

Merge or Rebase?

Both methods of code integration should be used when they are best suited. There are different opinions on when a certain method should be used.

Here are some links that describe situations when one method might be preferred over the other:

Ryan Frankel

Questions or Comments? Ask Ryan!

Ask a question and Ryan will respond to you. We strive to provide the best advice on the net and we are here to help you in any way we can.