IntelliJ IDEAでmerge、rebaseをする手順のまとめ

# 概要

IntelliJ IDEAでmergeおよびrebaseを行う操作手順のまとめです。下記の4つの状況について、まずコマンドラインで操作を確認し、次に同じ操作内容をIntelliJ IDEAで行う方法についてまとめています。

1. merge
2. squashするmerge
3. rebase
4. squashするrebase

**環境**

* Windows10 Professional
* IntelliJ IDEA 2017.02
* Git for Windows 2.14.1

**参考**

* [Git Documentation] (https://git-scm.com/doc)

# 前提

この記事ではtest.txtというテキストファイルを持つブランチをベースにし、このファイルを別々の場所で編集して、それをmergeまたはrebaseする手順をまとめています。
なお、同じファイルを別々のブランチで編集することになるのでmerge、rebase時にはコンフリクトが発生するようになっています。

masterおよびdevelopはリモートリポジトリ上にあり、developブランチは開発用のメインブランチという想定です。開発案件のブランチはここより切ります。
topicブランチは個別の開発案件用のブランチでローカルリポジトリ上にしかないという想定です。

この記事での操作は下記のブランチとコミットがある状態で始めます。

```text
    E---F---G topic
   /
  A---B---C---D develop
 /
O master
```

# [merge] (https://git-scm.com/docs/git-merge)の方法

## No fast forwardのmerge

topicブランチをdevelopブランチへマージする方法です。

### コマンドラインでの操作

#### merge前の状態

```text:before
    E---F---G topic
   /
  A---B---C---D develop
 /
O master
```

#### mergeの実行

developブランチを最新にします。

```bash
$ git checkout develop
$ git pull
```

developブランチにtopicブランチをマージします。

```bash
$ git merge --no-ff topic
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
```

コンフリクトが発生したのでテキストエディタで解消します。

**マージコミット**

commitするとコミットメッセージを編集する画面が立ち上がるので適宜編集して保存します。（この例ではデフォルトのままにしました）

```bash
$ git add .
$ git commit
```

#### merge後の状態

developブランチにtopicブランチをマージした状態です。

```text:after
    E---F---G topic
   /         \
  A---B---C---D---H develop
 /
O master
```

* Hがマージコミットです。

**コミットログの確認**

```bash
$ git log --graph --pretty=oneline
*   44c92e7c429f63a0c084dab728ec63ee4f97423c (HEAD -> develop) Merge branch 'topic' into develop
|\
| * 95fa3178a94e2df0e929c1bb2679bbde8cca28b2 (topic) commit G
| * fe1e730d91dc33b8a9239c43d0e3ed7b058925df commit F
| * 48e0b692d1c91de0b97e54117285a74aaadb6902 commit E
* | 83d0775fc5e616b247e0d3c35e2d9058544e5ce9 (origin/develop) commit D
* | 8ca5285e789ba346e259097400f2711e170c7143 commit C
* | 57006df83bf92863e34ba207ad018210ec6d2f92 commit B
|/
* 6c8ebf667369debdaa8ed27fc363f15194a61b0c commit A
* e5b3e09e47c70597e88b823ce2c397c244873bd3 (origin/master, origin/HEAD, master) first commit
```

### IntelliJでの操作

#### merge前の状態

* developブランチは最新の状態です。

![m0.png](https://qiita-image-store.s3.amazonaws.com/0/22772/d85f1d72-89eb-5e60-1a59-b9c486dc7cf8.png)

#### mergeの実行

メニュー -> VCS -> Git -> [Merge Changes...]

Strategyの"No fast forward"にチェックを入れます。

![m1.png](https://qiita-image-store.s3.amazonaws.com/0/22772/864ab7e3-899c-7106-901f-d7e17eecc1d9.png)

コンフリクトが発生すると下図の画面が表示されます。[Merge...]をクリックしてマージ画面でコンフリクトを解消します。

![m3.png](https://qiita-image-store.s3.amazonaws.com/0/22772/84671845-08ac-fbc2-7b9e-530083ae7479.png)

マージ画面です。左側がdevelopブランチの内容、右側がtopicブランチの内容です。中央がマージ結果です。直接編集することも`>>`や`<<`アイコンをクリックして差分を取り込むこともできます。
コンフリクトを解消したら最後に[Apply]をクリックして適用します。

![m5.png](https://qiita-image-store.s3.amazonaws.com/0/22772/46a641d4-62c3-32d3-bc22-bff05745c7da.png)

コンフリクトを解消したらコミットします。

#### merge後の状態

![m4.png](https://qiita-image-store.s3.amazonaws.com/0/22772/b45b9e97-60db-ed08-006f-8caf6e48bcee.png)

**コミットログの確認**

```bash
$ git log --graph --pretty=oneline
*   e680465a32b94714e47e543546881ea7ca487670 (HEAD -> develop) Merge branch 'topic' into develop
|\
| * b2f9eef3989524da84c8ac8a91b1d75daf167d11 (topic) commit G
| * b16cb2c5f152c93c057e40457df37ccdb7dc1f9a commit F
| * d403d0d09fe29c0e00c2919cc6764ef3ddcc128e commit E
* | f31f6ed109844669d56be2a788394390d25f8fb9 (origin/develop) commit D
* | d003cfb66879f10c26ac64de61df7e1daab05a47 commit C
* | bc11870d4fb28f816db080d0cb0dfdb3252c047a commit B
|/
* 8235288fe8a705cdae6a19c151330d545f0edaf1 commit A
* e5b3e09e47c70597e88b823ce2c397c244873bd3 (origin/master, origin/HEAD, master) first commit
```

## オプション`--squash`を付けたmerge

topicブランチのコミットを1つにまとめてdevelopブランチへマージする方法です。

### コマンドラインでの操作

#### merge前の状態

```text:before
    E---F---G topic
   /
  A---B---C---D develop
 /
O master
```

#### mergeの実行

developブランチを最新の状態にします。

```bash
$ git checkout develop
$ git pull
```

developブランチにtopicブランチをマージします。

```bash
$ git merge --squash topic
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Squash commit -- not updating HEAD
Automatic merge failed; fix conflicts and then commit the result.
```

コンフリクトが発生したのでテキストエディタで解消します。

**マージコミット**

commitするとコミットメッセージを編集する画面が立ち上がるので適宜編集して保存します。（この例ではデフォルトのままにしました）

```bash
$ git add .
$ git commit
```

#### merge後の状態

developブランチにtopicブランチをマージした状態です。

```text:after
    E---F---G topic
   /
  A---B---C---D---H develop
 /
O master
```

* Hがマージコミットです

**コミットログの確認**

```bash
$ git log --graph --pretty=oneline
* 7f7945a56ae0c6266b8ab60851acc79e278c38bc (HEAD -> develop) Squashed commit of the following:
* 498d68006af40f555be42be67f5d1deffcdf0e88 (origin/develop) commit D
* f20d8b108246f899851d534f806fa841bbb24991 commit C
* 4acfdd7c99891e07cdd1e2dc85ea9d4f52382c79 commit B
* 274d0beb3faa80e443400de93ad6ab4b20c2e74d commit A
* e5b3e09e47c70597e88b823ce2c397c244873bd3 (origin/master, origin/HEAD, master) first commit
```

### IntelliJでの操作

#### merge前の状態

![m-b0.png](https://qiita-image-store.s3.amazonaws.com/0/22772/b0af4b91-20a1-adb1-a48c-f5c271e4563d.png)

#### mergeの実行

メニュー -> VCS -> Git -> [Merge Changes...]

Strategyの"Squash commit"にチェックを入れます。

![m-b1.png](https://qiita-image-store.s3.amazonaws.com/0/22772/22507393-d9f3-a6a7-3bd3-a22d328a6750.png)

コンフリクトが発生すると下図の画面が表示されます。[Merge...]をクリックしてマージ画面でコンフリクトを解消します。

![m-b2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/50e9d3ab-d248-0663-923d-91c8e3a39cb0.png)

マージ画面です。コンフリクトを解消したら最後に[Apply]をクリックして適用します。

![m-b3.png](https://qiita-image-store.s3.amazonaws.com/0/22772/a3b77994-a51e-7839-dd8a-e75eb0b29f4f.png)

コンフリクトを解消したらコミットします。

#### merge後の状態

![m-b5.png](https://qiita-image-store.s3.amazonaws.com/0/22772/58d07778-7a7e-c21c-10ed-01f053e18f79.png)

**コミットログの確認**

```bash
$ git log --graph --pretty=oneline
* 6e9767304f72a1d9e5560e8bf2dda3a533a8e2f1 (HEAD -> develop) merge commit
* 649e1a881a50e9dcf74e7f72de9053c4efb455ec (origin/develop) commit D
* cc17bf387d5bfadaf9580842e969a74ef729cb2b commit C
* 2f6a8cf2473f06d45b826acabafd9a32d8d81e5a commit B
* 047907d7365708de135e4b819642bba6909ff1ec commit A
* e5b3e09e47c70597e88b823ce2c397c244873bd3 (origin/master, origin/HEAD, master) first commit
```

# [rebase] (https://git-scm.com/docs/git-rebase)の方法

## 通常のrebase

topicブランチをdevelopブランチでリベースする方法です。

### コマンドラインでの操作

#### rebase前の状態

```text:before
    E---F---G topic
   /
  A---B---C---D develop
 /
O master
```

#### rebaseの実行

developブランチを最新にします。

```
$ git checkout develop
$ git pull
```

topicブランチをdevelopブランチでリベースします。

```bash
$ git checkout topic

$ git rebase develop
First, rewinding head to replay your work on top of it...
Applying: commit E
error: Failed to merge in the changes.
Using index info to reconstruct a base tree...
M       test.txt
Falling back to patching base and 3-way merge...
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Patch failed at 0001 commit E
The copy of the patch that failed is found in: .git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
```

コンフリクトが発生したので解消します。この例ではtest.txtファイルで発生したので解消後にaddします。

```bash
$ git add test.txt
```

リベースするコミットがまだ残っているので続けます。この例ではこれでリベースが完了しました。

```bash
$ git rebase --continue

Applying: commit E
Applying: commit F
Using index info to reconstruct a base tree...
M       test.txt
Falling back to patching base and 3-way merge...
Auto-merging test.txt
Applying: commit G
Using index info to reconstruct a base tree...
M       test.txt
Falling back to patching base and 3-way merge...
Auto-merging test.txt
```

#### rebase後の状態

topicブランチを最新のdevelopブランチでリベースした状態です。

```text:after
                E'--F'--G' topic
               /
  A---B---C---D develop
 /
O master
```

**コミットログの確認**

```bash
$ git log --graph --pretty=oneline
* 5959d07d53f8e2571c39c8afda1c31f62be16877 (HEAD -> topic) commit G
* 5330a58a546548023e2e558dfc1b54aa244513a3 commit F
* e1d0f3ed4e4723c3e27460c99fcb0c968c9599ac commit E
* 18701c9765d0917b4065f468f4f3c4e6fa1cebc0 (origin/develop, develop) commit D
* 2099237fc81108d44ed537166cf6d5231ebb7f8e commit C
* eff2d54c8fcf4d95de15584209c4a95be3670b3d commit B
* b0f17d5a20f61f9c024c034d75c17e3c7ec9504d commit A
* a55b98baa1afe81926dfdf2254fb515c25d64ae7 (origin/master, origin/HEAD, master) Initial commit
```

### IntelliJでの操作

#### rebase前の状態

![m-c0.png](https://qiita-image-store.s3.amazonaws.com/0/22772/cec21462-3562-8110-8b4b-0fecaff7902b.png)

#### rebaseの実行

メニュー -> VCS -> Git -> [Rebase...]

Ontoにdevelopブランチを指定します。

![m-c1.png](https://qiita-image-store.s3.amazonaws.com/0/22772/5cf2202d-ce25-3ab8-b6f4-2eaa92165ff6.png)

リベースするブランチが表示されます。この例ではこのままの状態でリベースするので何も変えずに[Start Rebasing]をクリックします。

![m-c2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/69b3caee-5a7b-1d08-a20a-95cc9575a8a4.png)

コンフリクトが発生すると下図の画面が表示されます。[Merge...]をクリックしてマージ画面でコンフリクトを解消します。

![m-c3.png](https://qiita-image-store.s3.amazonaws.com/0/22772/4d97cd8e-7e53-251c-0154-6096907b6e82.png)

マージ画面でコンフリクトを解消します。

![m-c4.png](https://qiita-image-store.s3.amazonaws.com/0/22772/dc09c0bc-31e3-1e0f-848f-f1b0adffc5b1.png)

コミットメッセージを編集します。

![m-c6.png](https://qiita-image-store.s3.amazonaws.com/0/22772/b1b6d272-8a28-94ff-460b-d751cb3d87f5.png)

#### rebase後の状態

![m-c7.png](https://qiita-image-store.s3.amazonaws.com/0/22772/a65fd2f8-c289-2ec8-4f0b-411cba88ac3a.png)

**コミットログの確認**

```bash
$ git log --graph --pretty=oneline
* 613eb37ffe487adb40d47b1071beca096fb49ca8 (HEAD -> topic) commit G
* 50ece68c26a8b85222802a498030fb87f03e96f2 commit F
* c9ac8888398c2d88a86d248ec0ecfc888f0c7543 commit E
* 435ab3900bfe7d7878beefc318a2df39f081392d (origin/develop, develop) commit D
* af8f77d3d0ee6751e01f2cbbbaf0f32420a7fa3b commit C
* d2853bd9e7d1edaf7333f8eda8704bda6f685f03 commit B
* 6da82ff8b72713f3bd3b1f98726c35b47edbc8f2 commit A
* e5b3e09e47c70597e88b823ce2c397c244873bd3 (origin/master, origin/HEAD, master) first commit
```

## squashするrebase

topicブランチのコミットを1つにまとめてからdevelopブランチでリベースする方法です。

### コマンドラインでの操作

#### rebase前の状態

```text:before
    E---F---G topic
   /
  A---B---C---D develop
 /
O master
```

#### rebaseの実行

developブランチを最新にします。

```bash
$ git checkout develop
$ git pull
```

topicブランチをdevelopブランチでリベースします。

```bash
$ git checkout topic

$ git rebase -i develop
```

リベース画面が表示されるのでcommit F、commit Gをsquashするように編集します。

![s1.png](https://qiita-image-store.s3.amazonaws.com/0/22772/2dadeb00-3912-84f1-6b55-2b4305b5c518.png)
　　　↓
![s2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/b4da494a-cb3e-ea71-708c-7e1e6301545a.png)

コンフリクトが発生したので解消します。この例ではtest.txtファイルで発生したので解消後にaddします。

```bash
$ git add test.txt
```

リベースするコミットがまだ残っているので続けます。
リベースが完了するとコミットメッセージの編集画面が表示されるので編集します。この例では"commit E, F, G"としました。この例ではこれでリベースが完了しました。

```bash
$ git rebase --continue
[detached HEAD bde1270] commit E, F, G
 1 file changed, 1 insertion(+)
[detached HEAD f9cb135] commit E, F, G
 Date: Wed Oct 18 17:37:08 2017 +0900
 1 file changed, 3 insertions(+)
Successfully rebased and updated refs/heads/topic.
```

#### rebase後の状態

topicブランチのコミットを1つにまとめ最新のdevelopブランチでリベースした状態です。

```text:after
                H topic
               /
  A---B---C---D develop
 /
O master
```

* Hがリベースして1つにまとめたコミット

**コミットログの確認**

```bash
$ git log --graph --pretty=oneline
* f9cb135a840d24e2f884b36df6be4dd576d4e47d (HEAD -> topic) commit E, F, G
* 7b3e33be7c65f25e8d80bdf8b50167f53a974237 (origin/develop, develop) commit D
* 62b63a02b85b07c96e73ff9528b3234351cb7a97 commit C
* 20514031cd776e2ae76d752bf1a0dca21a74d235 commit B
* 7c031b917a9047ee23929ade0b063c15a822c3e6 commit A
* e5b3e09e47c70597e88b823ce2c397c244873bd3 (origin/master, origin/HEAD, master) first commit
```

### IntelliJでの操作

#### rebase前の状態

![m-d0.png](https://qiita-image-store.s3.amazonaws.com/0/22772/2a1cb3f7-675d-7730-2139-cb724129c8a8.png)

#### rebaseの実行

メニュー -> VCS -> Git -> [Rebase...]

Ontoにdevelopブランチを指定します。

![m-d1.png](https://qiita-image-store.s3.amazonaws.com/0/22772/9f760da6-0ecb-4de0-519f-f1677b93ae3a.png)

まとめたいコミットのactionをsquashにします。なお一番古いコミットはsquash（この例ではcommit E)できません。

![m-d2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/2920bd41-21fa-745c-1238-81247cc624a0.png)

コンフリクトが発生すると下図の画面が表示されます。[Merge...]をクリックしてマージ画面でコンフリクトを解消します。

![m-d3.png](https://qiita-image-store.s3.amazonaws.com/0/22772/76255645-74a5-e055-74a0-b30db8747afe.png)

マージ画面でコンフリクトを解消します。

![m-d4.png](https://qiita-image-store.s3.amazonaws.com/0/22772/1aeb5bea-0a5f-b269-7cc1-b875c6c8e6f8.png)

コミットメッセージの編集画面です。このメッセージはsquashによって1つにまとめられるコミットに対して付きます。

![m-d6.png](https://qiita-image-store.s3.amazonaws.com/0/22772/f6f94198-664b-d212-a481-b6f56428b51f.png)

#### rebase後の状態

![m-d7.png](https://qiita-image-store.s3.amazonaws.com/0/22772/b16de978-52d7-993c-b80b-b0920d961818.png)

**コミットログの確認**

```bash
$ git log --graph --pretty=oneline
* ac47b4e35a4915dad0d523f5ab696452f4b33d85 (HEAD -> topic) rebase commit E, F, G
* 8049734f4c33a6d7ff93ef01e42a8b2b54405d98 (origin/develop, develop) commit D
* 60af50c4d3054fe73c8d7e160b52c33f17af6441 commit C
* de58732bf088f2e3e4af9861a18f7aa3a69475c2 commit B
* f2899f0711b6b8f78a5911dd5dcb1b99b9de0fa6 commit A
* e5b3e09e47c70597e88b823ce2c397c244873bd3 (origin/master, origin/HEAD, master) first commit
```