If you have worked with Git, you must have come across merge commits. These commits are not created every time you merge, but only on some special scenarios. In this post, we will learn about merge commits and when are they created. At the end of the post, I will also provide a way to avoid them.
First, the simple fast-forward merge
Consider that you have a branch named featureX
which diverges from the main
branch as shown
below.
If you try to merge featureX
into main
using git merge featureX
, you will see the text
Fast-forward
in the merge output. Git uses this merge strategy when the commit pointed to by the branch that is being
merged into - main
in this case - is a direct ancestor of the branch that is being merged -
featureX
in this case.
In other words, if you start following the parent starting from the commit
pointed to by featureX
and you reach the commit pointed to by main
after some jumps, Git will
simply move (fast-forward) the main
branch pointer to the commit pointed to by featureX
.
main
branch as an example. I don’t mean to convey that merges can only happen into
the main
branch. Any Git branch can be merged into any Git branch.
When the main branch is NOT an ancestor of your feature branch
Consider the scenario below where the main
branch has moved ahead from the point where featureX
diverged.
In this case, the commit pointed to by main
is not an ancestor of the featureX
branch. So, Git
tries to find the common ancestor of the main
and featureX
. Then, Git performs a three-way merge
between the common ancestor commit, the commit pointed to by main
, and the commit pointed to by
featureX
. It creates a new snapshot that results from this merge and creates a “merge commit” on
the main
branch (or the branch being merged into).
Avoiding merge commits
To avoid “merge commits”, you can rebase the featureX
branch on the main
branch. After the rebase, the commit pointed to by main
will become an ancestor of featureX
. To learn more about rebasing, I suggest you read my post introducing git-rebase.