git fetchとブランチ取り込み系コマンドを解説

執筆時のgitのversion 2.20

対象のコマンド

| コマンド          | 第1引数              | 第2引数              |
|-------------------|----------------------|----------------------|
| git fetch         | <リモートリポジトリ名>         | <リモートブランチ名> |
| git merge         | <ローカルブランチ名> | --                   |
| git rebase        | <ローカルブランチ名> | --                   |
| git pull          | <リモートリポジトリ名>         | <リモートブランチ名> |
| git pull --rebase | <リモートリポジトリ名>         | <リモートブランチ名> |

それぞれのコマンドは、1つまたは2つのコマンドライン引数を取ります。
省略した場合については、[こちら](https://qiita.com/matsumotwoooo/items/b37b1ce988fb810eb8ac)をご覧ください。


## 以降リポジトリの状態を以下と仮定し説明します 

本記事では、上記5つのコマンドの引数を以下のリモートリポジトリ名とブランチ名を例にして説明します。

リモートリポジトリを `origin` という名前で、ローカルリポジトリに登録しているとしているとします。

また、リモート、ローカルそれぞれのリポジトリにあるブランチは以下とします。

+ リモートリポジトリ
  - master  
  - develop  

+ ローカルリポジトリ
  - コミット可能なブランチ
     - master  
     - develop  
  - リモートにあるブランチを追跡するためのブランチ
     - origin/master  
       リモート(`origin`)のmasterブランチを追跡している
     - origin/develop  
       リモート(`origin`)のdevelopブランチを追跡している


## フェッチ　(fetch)
リモートリポジトリにあるブランチの最新状態を、それを追跡しているローカルのブランチに反映させます。

``` bash
$ git fetch <リモート名> <リモートブランチ名>
```

例) リモート`origin`にある`develop`ブランチを、それを追跡しているローカルにある`origin/develop`にフェッチする。

```
$ git fetch origin develop
```
フェッチする前は、以下の状態であったとします。
`orgin/master` と `orgin/develop` は、リモートの最新状態を取り込めていません。

```
#リモートリポジトリ                  #ローカルリポジトリ

コミット6    *     master
　　　　     | \
コミット5    |  *  develop          
　　　　     |  |                 
コミット4    |  *                   *   develop origin/develop      
　　　　     | /                    |
コミット2    *                      *   master  origin/master
　　　　     |                      |
コミット1    *                      *

```

以下、コマンドの実行結果です。

```
#リモートリポジトリ                  #ローカルリポジトリ

コミット6    *     master
　　　　     | \
コミット5    |  *  develop          *   origin/develop
　　　　     |  |                   |
コミット4    |  *                   *   develop      
　　　　     | /                    |
コミット2    *                      *   master  origin/master
　　　　     |                      |
コミット1    *                      *
```

リモートの`develop`を、ローカルにあるコミット可能なブランチ `develop`  に取り込めたわけではないので注意してください。以降で解説する `マージ` と `リベース` どちらかで可能になります。


##  マージ　(merge)
引数に指定したローカルにあるブランチを、カレントブランチに取り込みます。

```bash
$ git merge <ブランチ名>　
```

例) リモート`origin`の`develop`ブランチを追跡するブランチである`origin/develop`をローカルの`develop`ブランチにマージする。
 
```
# developをチェックアウト
$ git checkout develop

# origin/developをマージ
$ git merge origin/develop
```

マージする前が、以下の状態だったとします。

```
#ローカルリポジトリ

コミット4       *  origin/develop
コミット3    *  |  develop
　　　　     | /            
コミット2    *     master origin/master                 
　　　　     |            
コミット1    *            
```

以下、コマンドの実行結果です。

```
#ローカルリポジトリ

コミット5    *     develop
　　　　     | \
コミット4    |  *  origin/develop
コミット3    *  |  
　　　　     | /            
コミット2    *     master origin/master        
　　　　     |            
コミット1    *            
```

マージで取り込めるブランチは、origin/developなどのリモートのブランチを追跡するブランチだけではありません。
ローカルにあるすべてのブランチを指定することができます。

**上記のブランチの状態から続けて、**以下のコマンドを実行してみましょう。

例) ローカルのdevelopブランチをローカルのmasterブランチにマージする。

```
# developをチェックアウト
$ git checkout master

# developをマージ
$ git merge develop
```
以下、コマンドの実行結果となります。

```
#ローカルリポジトリ

コミット5    *     master develop
　　　　     | \
コミット4    |  *  origin/develop
コミット3    *  |  
　　　　     | /            
コミット2    *     origin/master        
　　　　     |            
コミット1    *            
```


<br>
【おさらい】
リモートのdevelopを、ローカルのdevelopに取り込むまで。
1. リモートのdevelopを、`orgin/develop` にとりこむ(fetch)
2. origin/developを、ローカルの `develop`　にとりこむ(merge)

mergeは、ローカルのブランチに、指定したローカルの別のブランチをとりこむコマンドでした。
類似するコマンドに `rebase` があります。
違いは、ブランチの図をみて感じ取ってみてください。


## リベース　(rebase)
カレントブランチの根本を、現在のコミットから、引数に指定したブランチの最新コミットへ付け替えます。

```bash
$ git rebase <ブランチ名>
```

例) リモート`origin`の`develop`ブランチを追跡するブランチである`origin/develop`に、ローカルの`develop`ブランチをリベースする
 
```
# developをチェックアウト
$ git checkout develop

# developをorigin/developにリベース
$ git rebase origin/develop
```

リベースする前が、以下の状態だったとします。
マージとの比較をしやすくするため、同様の状況としました。

```
#ローカルリポジトリ

コミット4       *  origin/develop
コミット3    *  |  develop
　　　　     | /            
コミット2    *     master                  
　　　　     |            
コミット1    *            
```

以下、コマンドの実行結果です。

```
#ローカルリポジトリ

コミット3.1    *     develop
　　　　       | 
コミット4      *     origin/develop    
　　　　       |             
コミット2      *     master origin/master        
　　　　       |            
コミット1      *            
```

リベースには、ブランチはすっきりするというメリットがある一方、コミット3はなくなってしまいます。
マージとリベースは状況によって使い分けましょう。

<br>
基本的に、フェッチ、マージ、リベースを覚えておけば、ブランチの取り込みはできるわけですが、
フェッチとマージ、フェッチとリベースを同時に行える便利なコマンドもあるので、
良ければ覚えておきましょう。以降で解説します。

## プル　(pull)
リモートのブランチを、それを追跡しているローカルのブランチにフェッチし、さらにそのリモート追跡ブランチをカレントブランチにマージします。フェッチとマージの組み合わせです。

```bash
$ git pull <リモート名> <リモートブランチ名>
```
例) リモート`origin`にある`develop`ブランチを、ローカルの`develop`にプルします

```
#developブランチをチェックアウト
$ git checkout develop

# リモートのdevelopブランチをプルする
$ git pull origin develop
```

プルする前が、以下の状態だっとします。

```
#リモートリポジトリ                  #ローカルリポジトリ

コミット7    *     master
　　　　     | \
コミット6    |  *  develop           
コミット5    |  |                   *  develop
　　　　     |  |                   |                 
コミット4    |  *                   *  origin/develop         
　　　　     | /                    |
コミット2    *                      *   master  origin/master
　　　　     |                      |
コミット1    *                      *
```

以下、コマンドの実行結果です。

```
#リモートリポジトリ                  #ローカルリポジトリ

コミット8                           *      develop
コミット7    *     master           | \
　　　　     | \                    |  |
コミット6    |  *  develop          |  *   origin/develop
コミット5    |  |                   *  |    
　　　　     |  |                   | /                
コミット4    |  *                   *         
　　　　     | /                    |
コミット2    *                      *       master  origin/master
　　　　     |                      |
コミット1    *                      *
```
## プルリベース　(pull --rebase)
リモートのブランチを、それを追跡しているローカルのブランチにフェッチし、さらに、カレントブランチをそのリモートを追跡しているブランチにリベースします。フェッチとリベースの組み合わせです。

```bash

$ git pull --rebase <リモート名> <リモートブランチ名>
```
例) リモート`origin`にある`develop`ブランチをフェッチし、最新化された`orgin/develop`に、ローカルの`develop`をリベースします

```
#developブランチをチェックアウト
$ git checkout develop

# 1.リモートのdevelopを、origin/developにフェッチ
# 2.ローカルのdevelopを、origin/developにリベース
$ git pull --rebase origin develop
```
プル・リベースする前が、以下の状態だっとします。

```
#リモートリポジトリ                  #ローカルリポジトリ

コミット7    *     master
　　　　     | \
コミット6    |  *  develop           
コミット5    |  |                   *  develop
　　　　     |  |                   |                 
コミット4    |  *                   *  origin/develop         
　　　　     | /                    |
コミット2    *                      *   master  origin/master
　　　　     |                      |
コミット1    *                      *
```

以下、コマンドの実行結果です。

```
#リモートリポジトリ                     #ローカルリポジトリ

コミット5.1                            *   develop
コミット7       *     master           | 
　　　　        | \                    |  
コミット6       |  *  develop          *   origin/develop
　　　　        |  |                   |                
コミット4       |  *                   *         
　　　　        | /                    |
コミット2       *                      *   master  origin/master
　　　　        |                      |
コミット1       *                      *
```