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ブランチを作ります

$checkout -b develop
$ git branch

* develop
  master

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

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

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

    始めてのコミット

developブランチでcommit

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

今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

    始めてのコミット

今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 log
commit 6bd62ac51df549daaa45875da79391a75cbe4857
Author: hujisawa-ryosuke <vaaaval@gmail.com>
Date:   Fri Jun 2 12:08:10 2017 +0900

    masterメーン3

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

    masterメーン2

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

    masterメーン1

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ブランチの1〜3の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

そうすると

hello

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

masterメーン2

masterメーン3
=======
ddevelopメーン
>>>>>>> developメーン

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

直した後

hello

masterメーン1

masterメーン2

masterメーン3

ddevelopメーン

直したらひとまず–continueします

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

$ 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 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メーン2

masterメーン3

developの状態

 cat test.txt 
hello

ddevelopメーン

developmasterの状態

cat test.txt 
hello

masterメーン1

masterメーン2

masterメーン3

ddevelopメーン

藤沢瞭介(Ryosuke Hujisawa)
  • りょすけと申します。18歳からプログラミングをはじめ、今はフロントエンドでReactを書いたり、AIの勉強を頑張っています。off.tokyoでは、ハイテクやガジェット、それからプログラミングに関する情報まで、エンジニアに役立つ情報を日々発信しています!

未整理記事