git deep dive part 5: Merge branches
Tags: git
Published: 2020-05-07 15:43:53

---
title: git deep dive part 5: Merge branches
published: true
description: git deep dive
tags: git
---

In the [previous article](https://dev.to/kenakamu/git-deep-dive-part-4-use-reset-to-control-branch-and-three-trees-23a), I explain how to reset to specific commit and how to recover branches. In this article, I explain how git [merge](https://git-scm.com/docs/git-merge) works.

# What is merge

Merge means take all changes from another branch to current branch. My current git log looks like this.

```shell
* 867d90c (HEAD -> dev) update hello.txt
* 367c2d0 Update news
* 2adbcac (test, master) Add doc folder and files
* 16f1fa8 commit hello.txt
```
If I draw diagram, it should look like below.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ndxicaukbdgjqda7ctvb.png)
Let's say I want to merge dev branch to master. This means I want to take commit 367c2d0 and 867d90c in master branch.

# Fast forward merge

As I didn't add any change to master branch after dev branch is created, I can simply update master to point to latest dev commit 867d90c. git does this by default.

The merge results says "Fast-forward" as I expected.

```shell
gitDeepDive> git switch master
Switched to branch 'master'
gitDeepDive> git merge dev
Updating 2adbcac..867d90c
Fast-forward
 docs/news.txt | 1 +
 hello.txt     | 2 ++
 2 files changed, 3 insertions(+)
```
When I check commit log, I see master simply points to the last commit of dev branch. So no additional commit was created.

```shell
gitDeepDive> git log --oneline --graph
* 867d90c (HEAD -> master, dev) update hello.txt
* 367c2d0 Update news
* 2adbcac (test) Add doc folder and files
* 16f1fa8 commit hello.txt
```

# Recursive Merge

Now, let's go back to original commit and add new commit.

```shell
git reset --hard 2adbcac
echo "welcome">welcome.txt
git add welcome.txt
git commit -m "Add welcome"
```

Log shows I have new commit now.

```shell
gitDeepDive> git log --oneline --graph
* 7dce564 (HEAD -> master) Add welcome
* 2adbcac (test) Add doc folder and files
* 16f1fa8 commit hello.txt
```
I updated the diagram. It's obvious that I cannot do fast forward merge anymore.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/4yst33aevypww5yc7u8m.png)

Let's see how git handles this. git does recursive merge, which create new commit and merge all three commits. As there are no conflict of the files, it was straight forward.

```shell
gitDeepDive> git merge dev
Merge made by the 'recursive' strategy.
 docs/news.txt | 1 +
 hello.txt     | 2 ++
 2 files changed, 3 insertions(+)
gitDeepDive> git log --oneline --graph
*   b7a0c29 (HEAD -> master) Merge branch 'dev'
|\
| * 867d90c (dev) update hello.txt
| * 367c2d0 Update news
* | 7dce564 Add welcome
|/
* 2adbcac (test) Add doc folder and files
* 16f1fa8 commit hello.txt
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/yvhyv93mcpr59afi2qzs.png)

When I see the last commit, it has two parents which makes sense.

```shell
gitDeepDive> git cat-file commit b7a0c29
tree 88344b6b3d368bb76a7eee38623d4d7c7373b1b6
parent 7dce564c4836680b13a2489ca542b95a3a9fbfc1
parent 867d90cd40fa498bb171e9c785f21fadd8d64754
author Kenichiro Nakamura <kenakamu@microsoft.com> 1588863956 +0900
committer Kenichiro Nakamura <kenakamu@microsoft.com> 1588863956 +0900

Merge branch 'dev'
```

# Conflict when merge

Let's simulate conflict situation. I update hello.txt and news.txt.

```shell
git reset --hard 2adbcac
echo "good morning" >> hello.txt
echo "additioal info for news" >> docs\news.txt
git commit -am "update docs"
```
It creates new commit.

```shell
gitDeepDive> git log --oneline --graph
* c36490a (HEAD -> master) update docs
* 2adbcac (test) Add doc folder and files
* 16f1fa8 commit hello.txt
```
Now I do ``git merge dev`` and it shows conflict.

```shell
gitDeepDive> git merge dev
Auto-merging hello.txt
CONFLICT (content): Merge conflict in hello.txt
Auto-merging docs/news.txt
CONFLICT (content): Merge conflict in docs/news.txt
Automatic merge failed; fix conflicts and then commit the result.
```

I need to solve the conflicts. The easiest way for me to resolve the conflict is to use [mergetool](https://git-scm.com/docs/git-mergetool). I can specify any tool I want in config. I use Visual Studio code to resolve the conflict.

```shell
git mergetool
```
When I run the command, Visual Studio Code runs automatically and asked me to resolve news.txt first.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/3qjz1yju2awd98714v5t.png)

I take all the changes and close VSCode, then another window opens for hello.txt.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/rx92m2uhx19mzej065bb.png)

After I resolve all conflict, then I can complete the merge.
```shell
git merge --continue
```
I can edit the commit comment, but I just go ahead to close the editor. Now I see new commit added as expected.

```shell
gitDeepDive> git log --oneline --graph
*   a3d0879 (HEAD -> master) Merge branch 'dev'
|\
| * 867d90c (dev) update hello.txt
| * 367c2d0 Update news
* | c36490a update docs
|/
* 2adbcac (test) Add doc folder and files
* 16f1fa8 commit hello.txt
```

# Summary

The word "merge" sounds like it overwrite some files, but git won't. Git never change snapshot items, therefore, it simply creates new commit with merged blob. I will explain rebase, which is another merging technic in the next article.

[Go to next article](https://dev.to/kenakamu/git-deep-dive-part-6-rebase-258d)