Git Merge



The git merge command is used to incorporate commits from the independent lines of development into a single branch. When a target branch is merged into the current branch, the current branch will be updated to reflect the merge; however, the target branch will be untouched. The git merge command is often used in combination with the git checkout command to select the current branch and the git branch command with -d flag to remove the obsolete target branch.


How git merge works

The main purpose of git merge is to combine different series of commits into one unified history. The git merge is often used to combine two branches. In the following illustration, git merge takes two commit pointers, the branch tips, and search for the common base commit between them. When Git found the common base commit, it will create a new 'merge commit' that integrates the changes of each line of development.

In our example, we have two branches, Feature based off the master, and the master branch.

before git merge

Executing the git merge command will merge the Feature branch into the master, which is the current branch. Git will automatically decide which merge algorithm will be used.

after git merge

After running the git merge, Git will create a new merge commit. Those merge commits are special because they have two parent commits. When merging, Git will create a new merge commit by automatically using a merge algorithm to combine the two development lines into one history. If Git runs into the same portion of data modified in both histories, it will struggle to automatically combine them into one history. This is called the "version control conflict," and user intervention is needed to resolve it.


Preparing to merge

Before the merging process, there are some steps to take to secure that the merge goes smoothly.

Verify the receiving branch

Checking if the HEAD point to the right merge-receiving branch by running git status command. Then run the git checkout <receiving_branch> to switch to the receiving branch.

Fetch the latest remote commits

The receiving branch and merging branch should be updated with the latest remote changes. Run git fetch to pull the latest remote commits. After the fetch process is completed, run git pull to assure that the master branch has the latest updates.

Merging

After all the above steps of 'preparing to merge' have been executed, a merge can start by running git merge <branch_name> where the <branch_name> is the branch's name that will be merged into the receiving branch.


Fast Forward Merge

A fast-forward merge happens when the path from the current branch tip to the target branch is linear. To combine the two lines of development, Git has just to move the current branch tip up to the target branch tip rather than merging the branches. The fast forward merge combines histories so that all the commits that are reachable from the target branch are now available through the current branch.

The following example shows a fast forward merge of feature branch into master.

fast forward merge

The fast-forward is not always possible in all cases. We can not use a fast-forward when there is not a linear path to the target branch. If the branch has diverged, the fast-forward merge can not apply, and the solution will be to combine the two branches using a 3-way merge. The 3-way merges create a dedicated commit called the merge commit to combine two histories.

3 way merge

Many developers like to use the fast-forward merges (rebasing make it easy) for small features and bug fix, while the 3-way marge is often used to integrate the long-running features into the main code base.

The example below will demonstrate how to use the fast-forward merge by creating a new Feature branch, adding some commits to it, and integrating it into the main code base using a fast-forward merge.

# Creating a new Feature branch from the Master branch 
$ git checkout -b feature_branch

# Edit some files 
$ git add <file>
$ git commit -m "first commit in the feature"

# Edit some files 
$ git add <file>
$ git commit -m "last commit in the feature"

# Merge the Feature_branch into the Master branch 
$ git checkout master 
$ git merge feature_branch
$ git branch -d feature_branch

We run the git branch -d feature_branch to delete the 'feature_branch', because all the changes in this feature branch are now accessible through the Master branch.

If you need a merge commit during fast-forward merge to track all the merge that happens, the git merge command has a --no-ff that can be used as follows.

$ git merge --no-ff <branch>

The above command merges the specified <branch> into the current branch with the creation of a merge commit, even if it is a fast-forward merge.


3-way merge

In the following example, the master branch progress while the feature branch is in-progress. To merge the feature into master, it requires a 3-way merge. The 3-way merge is often used when developers work simultaneously on a large feature.

# Start a new feature branch 
$ git checkout -b feature_branch master 
# Modify some files 
$ git add <file>
$ git commit -m "first commit in the feature"
# Modify some file
$ git add <file>
$ git commit -m "last commit in the feature"
# Switch to the master branch 
$ git checkout master 
# Modify some files
$ git add <file>
$ git commit -m "so modifications to the master"
#  Merge the feature branch into the master 
$ git merge feature
$ git branch -d feature

In this case, Git can't do a fast-forward merge because it can't move the master pointer up to the feature branch without losing data.


Resolving conflict

When the same part of the same file has changed in two different branches, and you want to merge those branches, Git will not know which version to use. This situation is called a merge conflict; Git will stop before the merge commit and wait for a user intervention to resolve the conflict.

Git merging process uses edit/stage/commit workflow to resolve merge conflicts. When a merge conflict occurs, running git status will list which files need to be resolved. The following example shows what you will see if two different branches modified the same part of the 'demo.txt' file.


$ git status 
On branch master 
Unmerged paths: (use "git add/rm ..." as appropriate to mark resolution) both modified: demo.txt

How conflicts are presented

When a conflict occurs during a merge, Git will edit the content of the affected files using visual indicators that mark both sides of the conflicted content. Theses markers are: <<<<<<<, ======= and >>>>>>>.

some content not affected by the conflict 
<<<<<<< master 
this is conflicted text from master 
======= 
this is conflicted text from feature branch

The content before the ======= sign is the receiving branch, and the part after it is the merging branch.

When you find the conflicting section, you can choose which part you will keep. After resolving all the conflict merges, you can run git add to add all the conflicted files to the staging area. Then, finish with git commit to generate the merge commit.

Note: Remember that the merge conflicts only occur in a 3-way merge. It is impossible that conflicts happen in a fast-forward merge.



ExpectoCode is optimized for learning. Tutorials and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using this site, you agree to have read and accepted our terms of use, cookie and privacy policy.
Copyright 2020-2021 by ExpectoCode. All Rights Reserved.