現在のブランチの状況は
$ git log --graph --oneline --all
* 6b32b95 (filling-in-re-layout) Finish layout and routes
* b3c1ea4 (HEAD -> master) Add a full_title helper
| * d80cf26 (filling-in-leyout) Finish layout and routes
| * f8e15a5 (origin/master, heroku/master, rails-flavored-ruby) Add a full_title helper
|/
* d7a405c Complete advanced setup
* 592d781 (static-pages) Finish static pages
* 82cb5b9 (origin/static-pages) Add a Static Pages controller
* 81963a7 Add hello
* 50f4e2e Improve the README
* 293096f Initialize repository
ということで、d7a405c から二つに分かれて同じような作業を行ったと理解しました。
git の merge というのは、二つのブランチで別々の作業(例えば、片方はバグ修正、もう片方は新機能の追加)を行なったような場合に、両方の変更を取り込むために行うものです。別々の作業といっても同じ箇所に変更を加えてしまう場合があり(例えば、バグ修正のために修正した関数に新機能を追加したなど)、merge の際にコンフリクトが発生するのはよくあることなので、世間に出回っているコンフリクト解消のための記事にはそういう前提で書かれているものが多いと思います。
一方、両方のブランチで同じような変更を行った場合、変更のほとんどがコンフリクトしてしまいます。それらを merge することももちろん可能ですが、同じような変更をわざわざ merge する意味はあまりないと思います。そういう場合は、変更内容を確認した上で、片方のブランチを捨てる(不採用にする)という手もあると思います。
さて、現在のブランチの状況はこのように二つの枝分かれがあります。
+--- f8e15a5 (origin/master) --- d80cf26 (filling-in-leyout)
/
--- d7a405c +
\
+--- b3c1ea4 (master) --- 6b32b95 (filling-in-re-layout)
それぞれのコミットにおける変更内容を確認しましょう。
(f8e15a5 などの代わりに origin/master などで指定することもできます。)
$ git diff d7a405c..f8e15a5
(共通の親から f8e15a5 (origin/master) への変更内容)
$ git diff f8e15a5..d80cf26
(f8e15a5 (origin/master) から d80cf26 (filling-in-leyout) への変更内容)
$ git diff d7a405c..b3c1ea4
(共通の親から b3c1ea4 (master, HEAD) への変更内容)
$ git diff b3c1ea4..6b32b95
(b3c1ea4 (master) から 6b32b95 (filling-in-re-layout) への変更内容)
diff の見方ですが、行の先頭に -
がついて赤く表示された行が削除または変更された行、+
がついて緑で表示された行が追加または変更後の行になります。
また、二つのブランチの違いを表示するにはこうします。
$ git diff f8e15a5..b3c1ea4
(f8e15a5 (origin/master) と b3c1ea4 (HEAD -> master) の違い)
$ git diff f8e15a5..d80cf26
(d80cf26 (filling-in-leyout) と 6b32b95 (filling-in-re-layout) の違い)
これらがほとんど同じなら、どちらの枝分かれを採用しても良いと思われます。
ここで、現在の master があるブランチ (b3c1ea4, 6b32b95) を不採用にして、origin/master 側 (f8e15a5, d80cf26) を採用するとしましょう。例えば以下のようにします。(git は同じ結果になる方法が複数あるので、これは一例です。)
$ git checkout master
(master ブランチを操作するので、master ブランチに切り替えます。)
$ git reset --hard HEAD^
(master ブランチの現在位置を b3c1ea4 から d7a405c に移動します。)
(なお、--hard オプションは作業ディレクトに内容も d7a405c のものに変更するという意味です。)
$ git merge --ff-only origin/master
(master ブランチに origin/master の変更内容を取り込みます。)
(master ブランチは origin/master の祖先なので、master ブランチが origin/master の位置に移動するはず。)
$ git merge --ff-only filling-in-re-layout
(master ブランチに filling-in-re-layout の変更内容を取り込みます。)
(master ブランチは filling-in-re-layout の祖先なので、master ブランチが filling-in-re-layout の位置に移動するはず。)
git merge は枝分かれした二つのブランチの変更内容をマージするのが本来の使い方ですが、枝分かれしてない場合に先行しているブランチに追いつくためにも使えます。その際、間違って新たにマージコミットを作らないように --ff-only
オプションをつけています。
(すでに状況が変わってるようですが、基本的な考え方がわかれば応用できると思います。)
別の方法としては、master ブランチを一旦消して新たな位置に作り直したり、master ブランチを別の名前にして、別のブランチの名前を master に変更こともできますが、危険な香りがする(実際はそれほど危険ではありませんが)ので今回はやめておきます。
また、git branch でブランチを一覧表示できます。自分はよく -avv
オプションをつけます。
$ git branch -avv
* filling-in-layout b3c1ea4 Add a full_title helper
filling-in-leyout d80cf26 Finish layout and routes
filling-in-re-layout 6b32b95 Finish layout and routes
master b3c1ea4 [origin/master: ahead 1, behind 1] Add a full_title helper
rails-flavored-ruby f8e15a5 Add a full_title helper
static-pages 592d781 [origin/static-pages: ahead 1] Finish static pages
remotes/heroku/master f8e15a5 Add a full_title helper
remotes/origin/master f8e15a5 Add a full_title helper
remotes/origin/static-pages 82cb5b9 Add a Static Pages controller
remotes/
で始まるブランチはリモートブランチ、それ以外はローカルブランチです。自分が今いるブランチは *
がついてます。また、[origin/master: ahead 1, behind 1]
はリモートブランチに対応したブランチ、ahead はローカルが先行、behind はリモートが先行していることを意味します。ここで、ahead であれば git push
、behind であれば git pull
を行えば同期できますが、問題は両方ある場合で、まず git pull
してリモートの変更内容を取り込んで(コンフリクトした場合はそれを解消して)から git push
することになります。
ブランチは消さない限り残ってますので、不採用にしたブランチでもいつでも内容を確認できますし、チェックアウトして作業を再開することもできます。