デザイナー向けGit中級入門パート1(今度こそrebaseとmergeのちがいをマスターする)
書いた理由
デザイナーさんと仕事をして感じるのは、Gitで苦しんでる方がとても多いことです。最近はデザイナーさん向けのわかりやすいGit入門記事が増えてきて、熱心なデザイナーさんは基本的なコマンドや概念はとてもよく理解されているのですが、発展的なことたとえば「リベースしてmasterブランチにマージしといてねー」なんて言われると、固まったり、なんとなく実行するケースもまだまだ多いようです。けれどもGitはあくまでバージョン管理ソフトにすぎず、ここで悩んで時間を使うのは非本質的でとてももったいない! そこで、Gitのキーワードを「なんとなくわかる」から「わかる」に、そして「安心して使える」ようになって頂きたいとの思いからこの企画を考えました。
初回はrebaseとmergeのちがいについて取り上げます。両者ともブランチを統合するためのコマンドで、rebaseとmergeした結果がまったく同じ、なんてこともしばしばです。ですが、rebaseとmergeはまったく異なる概念であり、そのイメージをつかむことが「なんとなく」Gitを利用することから卒業するための近道になります。
rebase
「あるブランチに対するパッチ※をつくる」イメージ。
rebaseコマンドはしばしば、開発ブランチをmasterブランチの「パッチ」に変えるために利用されます。具体的には、今の開発ブランチの起点をmasterブランチの最先端に変えます。また、コミットがたくさんあるとごちゃごちゃしたパッチになりがちなので、コミットをまとめたりもできます。
※便宜上、記事では「ブランチに取り込むためのコミット」を「パッチ」と呼びます。
merge
「あるブランチにパッチをあてる」イメージ。
たとえば、ローカルの古い開発ブランチにリモートの最新の開発ブランチをパッチとして取り込んだり、masterブランチに(rebaseコマンドでmasterブランチのパッチとしてつくられた)開発ブランチを取り込んだりします。
rebaseについてもっとくわしく
さて冒頭でrebaseは「開発ブランチをmasterブランチの「パッチ」に変えるため」ためのコマンドだと書きましたが、これだけだと「ちょっと何言ってるかわからない(サンドウィッチマン)」と思うため、開発ブランチをmasterブランチの「パッチ」に変えるための "git rebase master" コマンドで具体的に何がおこるか解説しますね。
まず、masterのBコミットから派生させたdevelopブランチにいるとします。
A -> B -> C -> D :master
-> X -> Y -> Z :develop
"git rebase master"を実行すると、以下のようにdevelopブランチの開発の起点がmasterブランチの最新コミット(D)の後に変わっていることがわかります(起点を変えるからre-baseです)。developブランチはmasterブランチの最新コミットから開発が始まったことに変える、これが、developブランチをmasterブランチに対する最新の「パッチ」に変えるということです。
※masterブランチは頻繁に変わっていくので、"git rebase master"コマンドはなるべく開発中はこまめに実行してくださいね。
A -> B -> C -> D -> X -> Y -> Z :develop
ですので、このまま後はdevelopブランチをmasterにパッチにあてれば(マージすれば)いいのですが、developブランチの「X -> Y -> Z」コミットをそのままmasterブランチにマージするとごちゃごちゃしがちなんですね。たとえれば、masterブランチが日本史の年表だとすると、developブランチは一つのエピソードにすぎないので、内容をごちゃごちゃ書かずに一言「1192年鎌倉幕府成立」と書き加えた方が将来的に見通しがよくなるようなイメージです(わかりづらかったらごめんなさい)。
そこで、developブランチのコミットを一つにまとめるために"git rebase master"からmasterを抜いて、"git rebase"や"git rebase -i"コマンドを実行します(-iはinteractiveの略で、対話的にコミットをまとめることができます)。
※コミットをまとめる際にもコミット同士(X, Y, Z)でコンフリクトが発生すると結構大変なのですが当記事では割愛します。
rebaseをしないで開発ブランチをmasterブランチにマージすると何が起こるか
うまくいけばmasterブランチの歴史(A -> B -> C -> D)を維持したままマージできるかもしれませんが、コンフリクトが発生したら例えば「A -> B -> X -> Y -> Z -> C -> D」のようにmasterの歴史が改変された上でマージされる可能性があります。多くの場合、masterブランチは開発者全員が参照する「正史」なのでこの歴史が改変されることは望ましくありません。ですので、rebaseコマンドでmasterブランチの歴史を維持したまま開発ブランチをマージしていく方が良いと思います。
※実は"git rebase master"でコンフリクトが発生してmasterの歴史が改ざんされてぐちゃぐちゃになる場合もあり、一概にrebaseが正しいといえないことに注意が必要です。
さいごに
この記事でおぼろげにでもrebaseとmergeのイメージのちがいをご理解していただければ幸いです。
さて、記事中何度か「コンフリクト」というコトバが出てきました。こちらもデザイナーさんが「Git怖い嫌い滅びろ」と思う主な原因だと思うため、この記事がもしも好評ならばGit中級入門パート2「こわくないコンフリクト」を書きたいと思います。
今回書いてみてデザイナーさん向けにGit解説記事を書くのは思った以上にとても難しいことを痛感しました..