git mergeを勉強してみた


## はじめに
gitを使い始めて3ヶ月くらいです。
プルリクエストをおくってマージされたときの嬉しさが後押しして、gitを勉強してみる気がわいてきました。

同僚に「これ、rebaseした方がよかったんじゃないの？」といわれ、
健太「確かにそっすねー」と回答したが、やり方がよくわかっていない状況。
ということで、merge -> rebaseという順番で勉強してみようと思います。

## テスト用のリポジトリ作成
`master`というブランチを作成ます。
特に意味はないのですが、`Hello.java`というファイルをつくってこれをいろいろ修正してmergeを試してみます。
`.gitignore`も作成しておきましょう。


```java:Hello.java
class Hello {
    public static void main(String[] args) {
        System.out.println("hello");
    }
}
```

```.gitignore
*.class
```

```bash
$ git init ./
Initialized empty Git repository in /Users/kenta_suzuki/project/git/.git/

$ git add ./

$ git status                                                                                  [~/project/git]
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   .gitignore
        new file:   Hello.java

$ git commit -m '初めてのコミット'
[master (root-commit) 67c8090] 初めてのコミット
 2 files changed, 7 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Hello.java

$ git branch
* master

$ git log                                                                                     [~/project/git]
commit 67c809018dd292c5c84d957d0ae6c5eb03622dcd
Author: kenta <kenta_suzuki@dwango.co.jp>
Date:   Tue Dec 10 22:29:07 2013 +0900

    初めてのコミッ
```

とりあえず`master`ブランチに`Hello.java`がコミットされました。
ここから分岐させていきます。
`feature/world`上で`Hello.java`に`world`メソッドを追加してコミットします。

```bash
$ git checkout -b feature/world master

$ git log --decorate=full
commit 67c809018dd292c5c84d957d0ae6c5eb03622dcd (HEAD, refs/heads/master, refs/heads/feature/world)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date:   Tue Dec 10 22:29:07 2013 +0900

$ vim Hello.java
(ここで以下のdiffになるように修正)

$ git diff
 diff --git a/Hello.java b/Hello.java
index 89a9eee..a3a399b 100644
--- a/Hello.java
+++ b/Hello.java
@@ -2,4 +2,8 @@ class Hello {
     public static void main(String[] args) {
        System.out.println("hello");
     }
+
+    public static void world() {
+        System.out.println("world");
+    }
 }

$ git commit -a -m 'worldメソッドを追加'
[feature/world 08ffb74] worldメソッドを追加
 1 file changed, 4 insertions(+)

$ git log --decorate=full
commit 08ffb7444eafe390ea5ce8582b6c2ec0f2dd8a3f (HEAD, refs/heads/feature/world)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date:   Wed Dec 11 09:20:56 2013 +0900

    worldメソッドを追加

commit 67c809018dd292c5c84d957d0ae6c5eb03622dcd (refs/heads/master)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date:   Tue Dec 10 22:29:07 2013 +0900

    初めてのコミット
```

今度は`master`に戻り、`hello`メソッドを追加します。

```bash
$ git checkout master
Switched to branch 'master'

$ git log --decorate=full
commit 67c809018dd292c5c84d957d0ae6c5eb03622dcd (HEAD, refs/heads/master)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date:   Tue Dec 10 22:29:07 2013 +0900

    初めてのコミット

$ git diff
diff --git a/Hello.java b/Hello.java
index 89a9eee..b217fa8 100644
--- a/Hello.java
+++ b/Hello.java
@@ -2,4 +2,8 @@ class Hello {
     public static void main(String[] args) {
        System.out.println("hello");
     }
+
+    public static void hello() {
+        System.out.println("hello");
+    }
 }

$ git commit -a -m 'helloメソッドを追加'
[master ea93e48] helloメソッドを追加
 1 file changed, 4 insertions(+)

$ git log --decorate=full
commit ea93e4833c20246ea80d72761feab523c45ee8be (HEAD, refs/heads/master)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date:   Wed Dec 11 09:29:25 2013 +0900

    helloメソッドを追加

commit 67c809018dd292c5c84d957d0ae6c5eb03622dcd
Author: kenta <kenta_suzuki@dwango.co.jp>
Date:   Tue Dec 10 22:29:07 2013 +0900

    初めてのコミット
```

`feature/world`を`master`に`merge`してみます。

```bash
$ git merge feature/world
Auto-merging Hello.java
CONFLICT (content): Merge conflict in Hello.java
Automatic merge failed; fix conflicts and then commit the result.

$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
  (use "git add <file>..." to mark resolution)

        both modified:      Hello.java

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

マージをして修正部分が自動的にマージできないときはコリジョンがおこります。

```java:Hello.java
class Hello {
    public static void main(String[] args) {
        System.out.println("hello");
    }

<<<<<<< HEAD
    public static void hello() {
        System.out.println("hello");
=======
    public static void world() {
        System.out.println("world");
>>>>>>> feature/world
    }
}
```
以下のように修正。

```java:Hello.java
class Hello {
    public static void main(String[] args) {
        System.out.println("hello");
    }

    public static void hello() {
        System.out.println("hello");
    }

    public static void world() {
        System.out.println("world");
    }
}
```

コミットしてみます。

```bash
$ git commit -a -m 'worldメソッドをマージ'
[master 2889d24] worldメソッドをマージ

$ git log --decorate=full
commit 2889d24c5422fd145946ebd771aac193df7a3bb5 (HEAD, refs/heads/master)
Merge: ea93e48 08ffb74
Author: kenta <kenta_suzuki@dwango.co.jp>
Date:   Wed Dec 11 09:57:19 2013 +0900

    worldメソッドをマージ

commit ea93e4833c20246ea80d72761feab523c45ee8be
Author: kenta <kenta_suzuki@dwango.co.jp>
Date:   Wed Dec 11 09:29:25 2013 +0900

    helloメソッドを追加

commit 08ffb7444eafe390ea5ce8582b6c2ec0f2dd8a3f (refs/heads/feature/world)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date:   Wed Dec 11 09:20:56 2013 +0900

    worldメソッドを追加

commit 67c809018dd292c5c84d957d0ae6c5eb03622dcd
Author: kenta <kenta_suzuki@dwango.co.jp>
Date:   Tue Dec 10 22:29:07 2013 +0900

    初めてのコミット
```

## 最後に
mergeをやってみました。
次回はrebaseです。rebaseも今回と同じ流れでやってみて、コミットの履歴を追うときにどういった違いがあるのかをみていきます。