Development Git

Git Merge –no-ff Option

Understanding Git Merge no-ff Option

The easy merge capability of git is one of its strengths. During a merge, git uses fast-forward merge when it notices that the HEAD of the current branch is an ancestor of the commit you are trying to merge. In a fast-forward merge, there’s no new commit. Git just moves the pointer. If this behavior isn’t desirable, you can use the no-ff flag to create a new commit for the merge.

How Merge Looks With and Without Fast-Forward

After a fast-forward, your git history will look like this:

C0 —> C1  —> C2—> C3

For the same number of commits, here is a merge history without fast-forward:

In the first case, there is no indication that there was any branching. In the second case, the history is showing a C4 commit to indicate where the merge occurred.

Walking Through an Example

You will create a git repository, create a branch and then try the merges with and without fast-forward.

Section 1: Setup

First, you can create the git repository with the following steps:

$ mkdir my_project
$ cd my_project
$ git init
$ touch a.txt
$ git add -A
$ git commit -m "C0: Adding a.txt"

Now let’s create a branch called features and commit a few changes:

$ git branch features
$ git checkout features
$ touch b.txt
$ git add -A
$ git commit -m "C1: Adding b.txt"
$ touch c.txt
$ git add -A
$ git commit -m "C2: Adding c.txt"
$ touch d.txt
$ git add -A
$ git commit -m "C3: Adding d.txt"

Section2: Merge With Fast-Forwarding

Let’s go back to master branch and merge features branch into it:

$ git checkout master
$ git merge features

Output:

Updating 08076fb..9ee88eb
Fast-forward
b.txt | 0
c.txt | 0
d.txt | 0
3 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 b.txt
create mode 100644 c.txt
create mode 100644 d.txt

If you check the history, you’ll see:

$ git log --oneline
9ee88eb C3: Adding d.txt
c72b92c C2: Adding c.txt
2e4039e C1: Adding b.txt
08076fb C0: Adding a.txt

So, all of the commits from features branch is in the master branch now. If you continue making changes to master, there is no way to know when the features branch was merged into it.

Section 3: Without Fast-Forwarding

Repeat Section 1 for a new folder.

Then, try a merge without fast-forwarding:

$ git checkout master
$ git merge --no-ff feature

It will open up the following in your git’s default text editor:

Merge branch 'features'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.

Modify the comments. In this case, you can just add “C4: ” before “Merge branch ‘features’”. The output should look like this:

Merge made by the 'recursive' strategy.
b.txt | 0
c.txt | 0
d.txt | 0
3 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 b.txt
create mode 100644 c.txt
create mode 100644 d.txt

Now if you check the history, it should look like the following:

$ git log --oneline
e071527 C4: Merge branch 'features'
bb79c25 C3: Adding d.txt
692bd8c C2: Adding c.txt
a0df62a C1: Adding b.txt
7575971 C0: Adding a.txt

You can see that even though you have the exact same changes, this version of merge has the extra C4 commit which signifies the merging of features branch into master.

Conclusion

The git merge no-ff flag helps create a more readable history. It allows you to put tags that clearly shows where the merges occurred. It can save you time and effort during debugging.

Further Study:

References:

About the author

Zak H

Zak H

Zak H. lives in Los Angeles. He enjoys the California sunshine and loves working in emerging technologies and writing about Linux and DevOps topics.