Gitで物凄く重要な概念がブランチ。
ブランチですよブランチ、王様のブランチ。
僕の周りではブランチでGitに苦手意識を持っている人って結構多いです。
そこで今日はブランチを徹底的に学んで行きましょう!
ブランチとは?
ブランチってカタカナで書くとなんとなく難しそうな感じですが、並行して様々な作業と行えるという概念です。
例えば車の製造を想像して下さい。
- ボディ等の外装
- シート等の内装
- エンジン等の機関部
みたいにいくつかのパーツがまとまっていますよね?
で、これって決して1人や1つのチームで作るわけじゃないですよね。
外装製造ライン、内装製造ライン、機関部製造ラインのようにいくつかのラインに分かれて作っているはずです。
はい、もうブランチが理解できました!ようはこうやって並行して作業を進める、これがブランチです。
ブランチの考え方
Gitにおけるブランチも車の例と全く一緒です。
例えば既にHTMLとCSSからなるWebサイトを運営しているとします。
最もメインで重要なデフォルトのブランチをmasterブランチと言いますが、もし大きくデザインを変えたい時そのままmasterブランチで行いますか?
答えはNoです。
もちろん自分の中にルールがあれば良いんですが、基本的にmasterブランチ=完成版。
このルールが破綻してしまうとブランチはもちろんリポジトリの中身が破綻してしまいます。
まずはmasterブランチ=サーバー上に公開されている状態とルールを作っておきましょう(今回は例がWebページですが、ソフトウェアなら公開版)。
ブランチを切る
ではどうするかと言うと、作業用ブランチを作ります。
masterブランチから派生させて別のブランチ、例えば開発を意味するdevelopブランチを作成します。
この新しいブランチを作成する事をブランチを切ると言います。
新しい機能を追加しようかな?
じゃあブランチ切っといて!
みたいな感じで使います。
ブランチは複数作成できる
今は例としてdevelopブランチをあげましたが、ブランチは複数作成できます。
例えば
- 開発用のdevelopブランチ
- バグ修正のfixブランチ
のような感じ。
ちなみに派生したブランチから更に派生させる事も可能ですし、それぞれ独立してmasterブランチから派生させることもできます。
僕はそこまで試した事ないんですが多分上限もありません、いくつでも派生できます。
しかしきちんと派生した後のブランチを処理しないと無限に増えてしまうので、その辺は気をつけておきたいところです。
ブランチには慣れておこう
もちろん一人でGitを使っているだけならブランチなんて1~2つあれば十分、なんならよろしくないですがmasterブランチオンリーなんて人もいます。
しかしブランチの運用ルールが事前にきっちり定義されていれば、コミットログを見ればひと目でバグ修正の作業だなと言う目視もしやすくなります。
更に将来的に大きな開発に参加する時もブランチの概念に慣れておけばすんなり入れるでしょう。
今やWeb上だけで簡単に開発に参加できる時代、ブランチには絶対慣れておいた方が良いです。
マージする
では枝分かれしたブランチはどうなるでしょう?
もちろん最終的には公開しますよね、つまりmasterブランチと合流させる必要があります。
この切ったブランチを合流させる事をマージすると言います。
developブランチで開発中の新機能、全部完成したね!
masterブランチにマージして公開しよう!
マージは機能追加、バグ修正等々何回も使う事になります。
最終的にマージすると指定したブランチと合流してその内容が取り込まれます。
実践してみよう!
では実際にブランチを操作して覚えましょう!
まず前回までにやった現在の状況を整理すると、
- testディレクトリ内にindex.htmlがある
- 今まで2回コミットしていて、ファイルの中身は以下のようになっている
ブランチを作る
最初の作業はブランチを作成です。
Gitは一番最初にリポジトリを作った時にmasterブランチという1個のメインブランチを作成します。
つまり今居るのがmasterブランチです、念の為確認しておきましょう。
こんな感じでmasterブランチがある事が分かりました。
それではブランチ作成をしてみましょう。
ブランチ作成は先程ブランチ一覧を出力したgit branchコマンドの後に新しいブランチ名を続けて書けば作成できます。
今回は開発という意味でdevelopというブランチを作成してみたいと思います。
では実際に作成できているか確認します。
無事developが作成されていますね!
しかし実は今作成をしただけで、まだmasterブランチの中にいます。
よく見るとmasterの先頭に*(アスタリスク)がついていますね、これは現在居るブランチを示しています。
このままファイルの更新等をしてもそれはあくまでmasterブランチ上での作業、developブランチは作っただけ状態になってしまいます。
それでは困るので、developブランチに移動しましょう!
ブランチを移動することをチェックアウトと言います。
今回はmasterブランチからdevelopブランチにチェックアウトしました。
Switched to branchと書いてあるのでなんだか移動できてそうな雰囲気ですね・・・!
実際に確認してみましょう!
*がdevelopに移っていますね!
これで無事移動が完了しました!
ブランチ内で作業を行う
やっぱりdevelop、開発という事ですから何か新機能を追加したいところ。
そこで今回はCSSを追加したいと思います。
これでcssというディレクトリのstyle.cssが読み込めるようになりました。
ではcssディレクトリとstyle.cssファイルを作りましょう。
続いてcss/style.cssファイルにCSSを挿入します、今回はpタグの色をredに変えてみます。
試しにちゃんと挿入できているかcatコマンドで表示してみます。
大丈夫ですね、ではステージしてコミットしてみましょう!
無事コミットできました!
masterブランチを確認してみる
masterブランチの状態を見てみましょう。
ブランチを切ってdevelopブランチで作業しているので、masterブランチのindex.htmlは<link>タグが入っていないはずだしcssディレクトリも存在しないはずです。
masterブランチにチェックアウトしてみましょう。
masterブランチにチェックアウト出来たので、再びcatコマンドでindex.htmlを見てからlsコマンドでcssディレクトリが存在しているか見てみます。
見事にindex.htmlの<link>タグもcssディレクトリもありません!
つまりmasterブランチはdevelopブランチの影響を全く受けていないのでdevelopブランチは自由に開発ができる、という事が証明されました。
develop→masterにマージする
最後にdevelopブランチで行った作業をmasterブランチに反映させなければいけません。
マージはコマンドで指定したブランチを現在自分が居るブランチに反映させます。
という事はdevelopブランチをmasterブランチに反映させる為にはmasterブランチに居る必要があります。
先程の確認で既にmasterブランチに居るので、このままdevelopブランチを指定してみましょう!
これでマージ完了、無事developブランチの内容がmasterブランチに反映されました!
念には念を、catコマンドとlsコマンドでちゃんと反映されているか確認してみます。
全部ばっちり反映されていますね!
Fast-forward
さて、今回のブランチを切りマージする作業。
思い返して頂きたいんですが、作業をしたのはあくまでdevelopブランチでしたよね?
その間masterブランチには一切の変更がありません。
developブランチを作った時、実はdevelopブランチには今までのmasterブランチの履歴が全て引き継がれています。
言い換えればdevelopブランチはmasterブランチの延長線上でしかありません。
今回のようにmasterブランチに一切の変更が無く他のブランチをマージする事をfast-forward(早送り)と言います。
先程マージしたログを見てみるとFast-forwardと表示されています。
実際の開発現場では同時進行(並列)で様々な修正や追加が行われていて、自分がマージする時にはmasterブランチが既に他のブランチをマージしている場合が多々あり、Fast-forwardではないマージがほとんどです。
並列進行のマージ
では実際に並列進行した場合のマージがどうなるか見てみましょう。
先程の作業でまだmasterブランチに居るので、まずはdevelopブランチにチェックアウトします。
今回は新機能としてJavaScriptを追加します。
とりあえずjsディレクトリを作りnew.jsというからファイルを作ったので、作ったという事実をコミットしておきます。
ここからnew.jsに機能を追加・・・と思ったら実はindex.htmlにもう一文追加しなきゃいけない事が判明しました(という設定でいきます笑)。
これはバグです、のんきにJavaScriptを追加している場合じゃありません。
という事でfixというブランチを作成して、fixブランチ内でindex.htmlに追加していきます。
ですが開発途中のdevelopブランチからfixブランチを作ると、fixブランチはdevelopブランチの作業を引き継いでしまいます(空のjsディレクトリとjs/new.jsファイルがfixブランチにも取り込まれてしまう)。
そこで一度masterブランチにチェックアウトして、新しく(developブランチとは一切関係がない)fixブランチを作って行きます。
developブランチとは一切関係が無いfixブランチが作成できました!
念の為jsディレクトリがfixブランチに無い事を確認しておきましょう。
jsディレクトリはありませんね。
ではindex.htmlに追記して行きます!
修正が完了したのでステージ、コミットをしましょう!
無事コミット出来たので、このバグ修正を急いでmasterブランチに反映させます。
これで無事fixブランチのバグ修正がmasterブランチに取り込まれました。
並列世界の誕生
ここで一度状況を整理しておきましょう。
masterブランチはindex.htmlのバグ修正を行ったfixブランチを反映させました。
一方developブランチのindex.htmlはバグ発生前の状態です。
つまり内容が異なる2つのindex.htmlがあり、おまけにdevelopブランチには開発中のjs/new.jsがあります。
Fast-forwardの時のmasterブランチはdevelopブランチから見て一切の変更がありませんでしたが、今回はdevelopブランチから見てmasterブランチは違う状況です(developブランチには無い要素が親のmasterブランチにはある)。
ではdevelopブランチでの開発が終わったと仮定して、developブランチをmasterブランチにマージしてみましょう。
すると先程は一気にmerge出来ましたが、今回はVim(エディタ)が立ち上がったと思います。
Fast-forwardの時は不要でしたが、Fast-forwardではないマージの時はコミットメッセージを残す必要があります。
デフォルトは「Merge branch ‘develop’」となっていると思うので
- iキーを押して入力モードにする
- Merge branch ‘develop’を消す
- 「新機能js追加」と入力
- escキーを押してコマンドモードに戻る
- :wqキーを順番に押して最後にEnterキー
これでコミットメッセージの入力が行えます。
これが今回のマージの結果、先ほどと違ってFast-forwardの記載がありません。
今回のようにFast-forwardではないという事をそのまま、non-Fast-forwardと言います。
微妙な違いなんですが、Fast-forwardはコミットメッセージが不要に対してnon-Fast-forwardはコミットメッセージが必要になります。
マージをマスターしてGitを使いこなそう
今回はコマンドをたくさん打って大変だったと思います笑。
マージにはFast-forwardとnon-Fast-forwardの2種類がある事が分かりました。
ここで一つ疑問が浮かんで来ます。
今回はmasterブランチとdevelopブランチのindex.htmlのうち、developブランチに1行追加されただけでした。
しかし、もし同じindex.htmlにそれぞれのブランチで別々の内容が記載されていたら・・・?
次回はこの疑問を「もうコンフリクトは怖くない!Gitで起こる衝突問題を恐れず解決しよう」で解決して行きます!
コメント