git rebaseした時のコンフリクトを直して新しいブランチに二つのブランチを合流させてみる

気軽に使えるえけど一知半解でなんとなく使ってると身を滅ぼしかねないGit兄貴。僕の人間関係がコンフリクトしそうで恐ろしいです。今回は、他にもっといい方法があるのかもしれないけど、自分流に考えた`git rebase`で新しいブランチに二つのブランチを合流する方法をアウトプットとして書き残します。やりたいことは単純で、二つのブランチを無傷の状態で残しつつ新しいブランチに二つのブランチのコンフリクトを合流させるというものです。コンフリクトの選別をミスってもやり直せるように。

# 結論

先に結論だけ

```
//コンフリクトを直してcontinu
git rebase --continu
```

```
//普通はrebaseの後はコミットではなくマージする
git commit -m "二つのブランチを結合させた新しいブランチを作る"
```

```
//gitが謎のデタッチブランチに謎のコミットがあると教えてくれるのでそのコミットで新しいブランチを生成
git branch developmastere c5ab09d
```


# 初めてのコミット

新しく作った`test.txt`というファイルに`hello`と書いて、masterブランチでの初めてのコミットをしたとしましょう。`test.txt`というファイルに`hello`と書いてある状態でコミットした後にdevelopブランチを作ります

```git
$checkout -b develop
``` 

```git
$ git branch

* develop
  master

```


# 今ブランチの状態はどんな感じ

今、developブランチとmasterブランチでは互いに下記のようなコミットログを持っています。つまり、developブランチとmasterブランチは全く同じ状態ってこと。

```git
$ git log
commit 500fe42cdb75786a91ed9394b5d27c028c3b7097
Author: hujisawa-ryosuke <vaaaval@gmail.com>
Date:   Fri Jun 2 11:58:18 2017 +0900

    始めてのコミット
```

# developブランチでcommit 

じゃあ、今developブランチにいる状態で`test.txt`に`developメーン`と書いてコミットします。そーするとdevelopとmasterでは実態が変わります。

今developのコミットログはこんな感じ

```git
git log
commit a66d5795d0a1fcfdbcf1b3855424fc3bd5bc5314
Author: hujisawa-ryosuke <vaaaval@gmail.com>
Date:   Fri Jun 2 12:03:30 2017 +0900

    developメーン

commit 500fe42cdb75786a91ed9394b5d27c028c3b7097
Author: hujisawa-ryosuke <vaaaval@gmail.com>
Date:   Fri Jun 2 11:58:18 2017 +0900

    始めてのコミット
```

今masterのコミットログはこんな感じ

```

git log
commit 500fe42cdb75786a91ed9394b5d27c028c3b7097
Author: hujisawa-ryosuke <vaaaval@gmail.com>
Date:   Fri Jun 2 11:58:18 2017 +0900

    始めてのコミット


```

# masterブランチを三回コミット

ここで、大胆にもmasterブランチで三回コミットしました。内容は、一回コミットするたびに「masterメーン」を書いていくだけですが。

今masterの状態はこんな感じ

```git

git log
commit 6bd62ac51df549daaa45875da79391a75cbe4857
Author: hujisawa-ryosuke <vaaaval@gmail.com>
Date:   Fri Jun 2 12:08:10 2017 +0900

    masterメーン３

commit 4b6db8881ff9355d2d88eccc9b1d693d13f557da
Author: hujisawa-ryosuke <vaaaval@gmail.com>
Date:   Fri Jun 2 12:06:59 2017 +0900

    masterメーン２

commit 8c3f955a37430f06e7b9e4e30ea2506170df5547
Author: hujisawa-ryosuke <vaaaval@gmail.com>
Date:   Fri Jun 2 12:06:17 2017 +0900

    masterメーン１

commit 500fe42cdb75786a91ed9394b5d27c028c3b7097
Author: hujisawa-ryosuke <vaaaval@gmail.com>
Date:   Fri Jun 2 11:58:18 2017 +0900

    始めてのコミット
:



```


今developの状態はこんな感じ

```
git log
commit a66d5795d0a1fcfdbcf1b3855424fc3bd5bc5314
Author: hujisawa-ryosuke <vaaaval@gmail.com>
Date:   Fri Jun 2 12:03:30 2017 +0900

    developメーン

commit 500fe42cdb75786a91ed9394b5d27c028c3b7097
Author: hujisawa-ryosuke <vaaaval@gmail.com>
Date:   Fri Jun 2 11:58:18 2017 +0900

    始めてのコミット

```

# コンフリクト起こる

この状態でgit rebaseしたらどーなるでしょうか。コンフリクトします。developでコミットした`developメーン`はmasterに存在しないしmasterブランチの１〜３のmasterメーンはdevelopブランチに存在しないからです。どっちの変更を反映していいかわからないからコンフリクトします。では、ためにしコンフリクトを起こしてみます。

まずgit branchでdevelopにいることを確認して

```
 git branch
* develop
  master
```

```
git rebase master
```

# コンフリクトしました

```
git rebase master
First, rewinding head to replay your work on top of it...
Applying: developメーン
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
error: Failed to merge in the changes.
Patch failed at 0001 developメーン
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".

```


# コンフリクトを直す

ここがコンフリクトしてる場所だから

```
CONFLICT (content): Merge conflict in test.txt
```
開く

```
vi test.txt
```

そうすると

```vim
hello

<<<<<<< HEAD
masterメーン1

masterメーン２

masterメーン３
=======
ddevelopメーン
>>>>>>> developメーン
```

はい！案の定、test.txtに関してどっちの変更を取り込めばいいか迷ってしまっていますね。今回は、どっちの変更も取り込むことにしましょう〜

直した後

```
hello

masterメーン1

masterメーン２

masterメーン３

ddevelopメーン

```


# 直したらひとまず--continueします

rebaseはコンフリクトを直した後にcommitするんじゃなしに--continueします。はい、やってみましょう

```git
$ git rebase --continu
test.txt: needs merge
You must edit all merge conflicts and then
mark them as resolved using git add
```

merge しなさいとおっしゃられていますが、仮に僕がマージしたくないとしたらどうでしょうか。ここでやっと本題の`git rebaseした時のコンフリクトを直して新しいブランチに二つのブランチを合流させてみる`に入ります。この状態で ` git branch `をすると下記のような表示になっています。

```git
 git branch
* (no branch, rebasing develop)
  develop
  master
```

要はrebasing途中で、developでもないmasterでもないわけのわからないブランチにいるぜ！ってことです。rebasingを完了させるにはマージする訳ですが、マージしたくない場合どうすればいいでしょうか。

```
git commit -m "二つのブランチを結合させた新しいブランチを作る"
```

コミットしてしまいましょう。そして `git checkout develop`しようとすると、gitは下記のように親切にも教えてくれます。

```
git checkout develop
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

  c5ab09d 二つのブランチを結合させた新しいブランチを作る

If you want to keep it by creating a new branch, this may be a good time
to do so with:

 git branch <new-branch-name> c5ab09d

Switched to branch 'develop'

```
これは、developに行きたいけれど、どこにも反映されてない変更があるぜ。ってことです。この変更を反映するには新しいブランチを作ればいいよ！と教えてくれます。

```
 git branch developmastere c5ab09d
```

```
git checkout developmastere
Switched to branch 'developmastere'
```

はい、これでdevelopブランチとmasterブランチの変更を取り込んだ新しいブランチが作成されました。developブランチもmasterブランチも無傷で新しいブランチができましたね。仮にコンフリクトの修正でミスってもこれならやり直せます。

masteの状態

```
 cat test.txt 
hello

masterメーン1

masterメーン２

masterメーン３

```

developの状態

```
 cat test.txt 
hello

ddevelopメーン

```
developmasterの状態

```
cat test.txt 
hello

masterメーン1

masterメーン２

masterメーン３

ddevelopメーン

```
# 参考
[git rebaseした時のコンフリクトを直して新しいブランチに二つのブランチを合流させてみる](http://off.tokyo/blog/2017/06/02/git-rebase%E3%81%97%E3%81%9F%E6%99%82%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%95%E3%83%AA%E3%82%AF%E3%83%88%E3%82%92%E7%9B%B4%E3%81%97%E3%81%A6%E6%96%B0%E3%81%97%E3%81%84%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81/)