Git Merge - Working with branches

Git

In this tutorial we will learn to merge branches in Git.

So, we have already learned in the previous tutorials how to create branches and how to checkout branches.

Merging branches

To merge a given branch into the currect branch we use the git merge [branch-name] command.

So, if we are on master branch (i.e., current branch) and we run the git merge dev command then we will merge the dev branch (i.e., target branch) into the master branch.

Before merge:

$ ls -la
total 0
drwxr-xr-x   5 yusufshakeel  staff  160 Oct  5 19:47 .
drwxrwxrwx  30 yusufshakeel  staff  960 Oct  2 22:48 ..
drwxr-xr-x  15 yusufshakeel  staff  480 Oct  8 16:43 .git
-rw-r--r--   1 yusufshakeel  staff    0 Sep 18 21:10 index.php
drwxr-xr-x   3 yusufshakeel  staff   96 Sep 12 19:46 js

Merging...

$ git merge dev
Updating f066f07..ca522cf
Fast-forward
 sample.php | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 sample.php

After merge:

$ ls -la
total 0
drwxr-xr-x   6 yusufshakeel  staff  192 Oct  8 16:44 .
drwxrwxrwx  30 yusufshakeel  staff  960 Oct  2 22:48 ..
drwxr-xr-x  15 yusufshakeel  staff  480 Oct  8 16:44 .git
-rw-r--r--   1 yusufshakeel  staff    0 Sep 18 21:10 index.php
drwxr-xr-x   3 yusufshakeel  staff   96 Sep 12 19:46 js
-rw-r--r--   1 yusufshakeel  staff    0 Oct  8 16:44 sample.php

You can see that sample.php file got added to the master branch working directory after the merge from the dev branch.

Note! The merge was a Fast-Forward merge (more on that later in this tutorial).

What happens when we merge?

When we merge the target branch into the current branch, the current branch gets updated to reflect the changes. So, new files get added, exisiting files, if modified, gets updated. But the target branch remains unaffected.

So, in the above merge example the target branch is the dev branch and the current branch is the master branch.

When we perform the merge operation a new file (sample.php) from the target (dev) branch is added to the current (master) branch.

Fast forward merge

Git performs a Fast forward merge if there is a linear path between current branch and target branch.

Example: We have a master branch and we create a new dev branch from it. Then we checkout the dev branch and commit some changes. And finally we return back to the master branch and merge the dev branch changes into the master branch.

After the fast forward merge the pointer pointing at the last commit of the master branch is moved forward to point at the last commit of the dev branch.

Example

On master branch.

$ git branch
* master

$ ls -la
total 0
drwxr-xr-x   5 yusufshakeel  staff  160 Oct  8 17:21 .
drwxrwxrwx  30 yusufshakeel  staff  960 Oct  2 22:48 ..
drwxr-xr-x  15 yusufshakeel  staff  480 Oct  8 17:22 .git
-rw-r--r--   1 yusufshakeel  staff    0 Sep 18 21:10 index.php
drwxr-xr-x   3 yusufshakeel  staff   96 Sep 12 19:46 js

Create a new dev branch and checkout.

$ git checkout -b dev
Switched to a new branch 'dev'

$ git branch
* dev
  master

$ ls -la
total 0
drwxr-xr-x   6 yusufshakeel  staff  192 Oct  8 17:26 .
drwxrwxrwx  30 yusufshakeel  staff  960 Oct  2 22:48 ..
drwxr-xr-x  15 yusufshakeel  staff  480 Oct  8 17:27 .git
-rw-r--r--   1 yusufshakeel  staff    0 Sep 18 21:10 index.php
drwxr-xr-x   3 yusufshakeel  staff   96 Sep 12 19:46 js

Create a new file sample.php on the dev branch and commit it.

$ touch sample.php

$ ls -la
total 0
drwxr-xr-x   6 yusufshakeel  staff  192 Oct  8 17:26 .
drwxrwxrwx  30 yusufshakeel  staff  960 Oct  2 22:48 ..
drwxr-xr-x  15 yusufshakeel  staff  480 Oct  8 17:27 .git
-rw-r--r--   1 yusufshakeel  staff    0 Sep 18 21:10 index.php
drwxr-xr-x   3 yusufshakeel  staff   96 Sep 12 19:46 js
-rw-r--r--   1 yusufshakeel  staff    0 Oct  8 17:26 sample.php

$ git status
On branch dev
Untracked files:
  (use "git add ..." to include in what will be committed)

	sample.php

nothing added to commit but untracked files present (use "git add" to track)

$ git add .

$ git commit -m 'initial commit'
[dev 80cbf0b] initial commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 sample.php

Checkout the master branch and merge the dev branch.

$ git checkout master
Switched to branch 'master'

$ git branch
  dev
* master

$ git merge dev
Updating 0e19bc1..80cbf0b
Fast-forward
 sample.php | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 sample.php

$ ls -la
total 0
drwxr-xr-x   6 yusufshakeel  staff  192 Oct  8 17:28 .
drwxrwxrwx  30 yusufshakeel  staff  960 Oct  2 22:48 ..
drwxr-xr-x  15 yusufshakeel  staff  480 Oct  8 17:28 .git
-rw-r--r--   1 yusufshakeel  staff    0 Sep 18 21:10 index.php
drwxr-xr-x   3 yusufshakeel  staff   96 Sep 12 19:46 js
-rw-r--r--   1 yusufshakeel  staff    0 Oct  8 17:28 sample.php

3-way merge

Git performs a 3-way merge when the current branch has also moved.

Example: We have a master branch and we create a new dev branch from it to develop a new feature. At this point, pointer for the dev and master branch are pointing at the same last commit.

We checkout the dev branch and start committing the changes. So, the dev branch pointer starts to move forward.

While we are developing the new feature on the dev branch, lets say, other developers in our project add their new feature and merged it into the master branch. So, now the master branch pointer is also moved forward.

Now, we are done with our new feature development so, we checkout the master branch and merge the dev branch into it. Since the master branch last commit pointer has moved forward because of the commit from the other developers so, Git performs 3-way merge.

Example

On master branch.

$ git branch
* master

$ ls -la
total 0
drwxr-xr-x   5 yusufshakeel  staff  160 Oct  8 18:01 .
drwxrwxrwx  30 yusufshakeel  staff  960 Oct  2 22:48 ..
drwxr-xr-x  15 yusufshakeel  staff  480 Oct  8 18:01 .git
-rw-r--r--   1 yusufshakeel  staff    0 Sep 18 21:10 index.php
drwxr-xr-x   3 yusufshakeel  staff   96 Sep 12 19:46 js

Create a new dev branch and checkout.

$ git checkout -b dev
Switched to a new branch 'dev'

$ git branch
* dev
  master

$ ls -la
total 0
drwxr-xr-x   5 yusufshakeel  staff  160 Oct  8 18:01 .
drwxrwxrwx  30 yusufshakeel  staff  960 Oct  2 22:48 ..
drwxr-xr-x  15 yusufshakeel  staff  480 Oct  8 18:04 .git
-rw-r--r--   1 yusufshakeel  staff    0 Sep 18 21:10 index.php
drwxr-xr-x   3 yusufshakeel  staff   96 Sep 12 19:46 js

Create a new file sample.php on the dev branch and commit it.

$ touch sample.php

$ git status
On branch dev
Untracked files:
  (use "git add ..." to include in what will be committed)

	sample.php

nothing added to commit but untracked files present (use "git add" to track)

$ git add .

$ git commit -m 'initial commit'
[dev 4038853] initial commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 sample.php

Checkout the master branch and commit some changes.

$ git checkout master
Switched to branch 'master'

$ ls -la
total 8
drwxr-xr-x   5 yusufshakeel  staff  160 Oct  8 18:08 .
drwxrwxrwx  30 yusufshakeel  staff  960 Oct  2 22:48 ..
drwxr-xr-x  15 yusufshakeel  staff  480 Oct  8 18:09 .git
-rw-r--r--   1 yusufshakeel  staff   32 Oct  8 18:08 index.php
drwxr-xr-x   3 yusufshakeel  staff   96 Sep 12 19:46 js

$ vi index.php 

$ git status
On branch master
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

	modified:   index.php

no changes added to commit (use "git add" and/or "git commit -a")

$ git add .

$ git commit -m 'update'
[master 9a971ed] update
 1 file changed, 5 insertions(+)

Now the master branch has moved forward. And now we are going to merge the dev branch into master.

$ git merge dev
Merge made by the 'recursive' strategy.
 sample.php | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 sample.php