【gitをソフト開発で使いこなそう:第5回】ブランチってどんな場面で使うんだろう?

次回の記事

  terapotan.hatenablog.jp

前回の記事

terapotan.hatenablog.jp

連載記事一覧

terapotan.hatenablog.jp

前回ブランチはある特定のコミットを指すものと解説しました。しかし、この機能をどのような場面で活用するのかは解説していません。今回はブランチの活用方法を解説していきます。

どんな時にブランチを使うのか

ブランチを使わなかったら

ここではブランチの使用場面を理解するために次のような状況を考えてみましょう。

今あなたはgitを使ってソフトウェアを開発しています。
ソフトウェアを開発している人

ソフトウェアの開発は順調に進み何回かコミットをした後無事ソフトウェアをリリース(公開)することが出来ました。(もちろん実際のソフトウェア開発ではリリースまでに何百回のコミットが行われます。今回は例を簡単にするためにこのようにしました。)

3回目のコミットをリリース

その後あなたはリリースに機能を追加するために、ここからさらに1回コミットを行いました。

機能追加のためリリースからもう一度コミット

そんな時です。リリースしたソフトウェアを使用している方から「何かソフトがバグったぞ!修正版を出してくれ!」と言われてしまいました。

バグったぞ!修正しろ!と開発者に詰め寄るクレーマー

あなたは困ってしまいました。リリースの修正と機能追加は別々に行いたいと思っていたからです。
このままcommitDにバグの修正を入れてコミットを行いリリースしてしまうと、バグの修正だけでなく追加した機能までリリース(公開)されてしまいます。

リリース

さて、一体どうすればいいのでしょうか。

どうやってブランチを使うのか

この問題はブランチを作ることによって解決することが出来ます。

まずリリースしたコミットに予めreleaseブランチを作成しておきます。(名前はどんな名前でも構いません)

リリースしたコミットに予めreleaseブランチを作成

今回の例のようにリリースしたコミットに戻って修正したい場合、初めに以下のコマンドを実行してHEADをreleaseブランチに移動させます。

git checkout release

HEADをreleaseに移動

続いてファイルを変更しコミット(今回の例であれば不具合を修正してコミット)します。すると下の図のように履歴を分岐させることが出来ます。

履歴を分岐した時の図

上の図のような状態にしておけば、機能追加の作業に戻ることも簡単ですし(git checkout masterを実行すればよい)何回でもリリースの修正を行うことが出来ます。

ブランチを利用すれば履歴を分岐させることが出来ます。今回紹介した例以外にもブランチには様々な使われ方がありますが基本の機能は履歴を分岐させることです。

Column:ブランチはポインタだ!

前回でも何回か言った通り「ブランチはコミットを指すポインタ」です。

ブランチが履歴を分岐させるのに使われることが多いせいか、ブランチを分岐したコミットそのものと勘違いしてしまう人がいるそうです。
ブランチをそう解釈してしまうと、今後の説明がさっぱりわからなくなってしまいます。

もしブランチの意味を間違って覚えていた方はこれを機に覚えなおしてください。

もし実際にやるとしたら...?

練習のため上の例を実際のgit上で実行してみます。

まず上の例を再現するために適当なファイルを3回コミットします。
コミットを行いGitBash上でgit log --oneline --graphを入力して実行すると、次のような結果が表示されます。

* 99ff0fb (HEAD -> master) commitC
* 950c756 commitB
* fd1a78e commitA

例の通りmasterブランチがcommitCを指し、HEADがmasterブランチを指していることが分かります。
HEADがmasterブランチを指していることを確認した上で、git branch releaseを実行しreleaseブランチを新たに作成します。
git log --oneline --graphを実行すると、確かにcommitCを指すreleaseブランチが作成されていることが分かります。

* 99ff0fb (HEAD -> master, release) commitC
* 950c756 commitB
* fd1a78e commitA

HEADがmasterを指している状態のまま、適当なファイルをコミットします。
再度git log --oneline --graphを実行すると次のようになってcommitDがコミットされていることがわかります。

* 7f31df0 (HEAD -> master) commitD
* 99ff0fb (release) commitC
* 950c756 commitB
* fd1a78e commitA

上の例では、このタイミングで「リリースの修正をしろ!」と言われていました。
HEADをreleaseブランチに移動させればリリースの修正を行うことが出来ます。
次のコマンドを実行しましょう。

git checkout release

処理の結果を確認すると下のようになります。

* 99ff0fb (HEAD -> release) commitC
* 950c756 commitB
* fd1a78e commitA

(結果を見るとcommitDがありません。「commitDが消えてしまったのではないか」と思われるかもしれませんが、実際にはそうではなくただ結果に表示されていないだけです。git checkout masterを実行すると再度commitDが結果に表示されます。)

本来の開発であればここでリリースの修正を行いますが、今回は例であるため適当なファイルを追加してコミットします。
処理結果は次の通りです。

* f022dd9 (HEAD -> release) commitE
* 99ff0fb commitC
* 950c756 commitB
* fd1a78e commitA

リリースの修正が終わりました。機能開発に戻りたい場合はgit checkout masterを実行します。

* 7f31df0 (HEAD -> master) commitD
* 99ff0fb commitC
* 950c756 commitB
* fd1a78e commitA

ブランチをgit checkoutコマンドで切り替えるだけで機能開発とリリース修正を行ったりきたりすることが出来るようになりました。

Column:'detached HEAD'...?

今まで挙げた例では、HEADは必ずブランチを指していましたが 「git checkout [コミットID]」というコマンドを実行することで、[コミットID]のコミットをHEADが直接指す状態にすることが出来ます。(HEADがこのような状態になっていることをdetached HEADといいます)

今回までに解説したようなgitの使い方ではdetached HEADは意図的に起こさない限り、そう起こりませんがより高度なコマンド・操作を行うようになってくると意図せずdetached HEADになってしまうことがあります。

detached HEADの状態のまま放っておくことは好ましくありません。なぜなら、コミットを指すものがHEADしかないためHEADを別のブランチに移動させるとどのポインタ(HEAD,ブランチ)からも参照されていないコミットが発生してしまうからです。このようなコミットは一定期間経つとgitによって削除されてしまう可能性があります。

gitではHEADの移動時にdetached HEADが発生した場合「You are in 'detached HEAD' state....」から始まる警告メッセージが表示されるようになっています。

次回予告

次回は二つのブランチの履歴をまとめる「マージ」について解説します。

この記事について

この記事について、誤字や間違っている所がある場合は私のTwitterか、コメント欄から連絡をお願いします。

参考文献

Pro Git

Git,GitHubの使い方について、非常に詳しく丁寧に解説されています。
ですが、内容が初心者には難しいと思われるため一度入門記事等を読んで一通りGit,Githubを勉強してから読まれると理解が深まると思います。
pdf形式であれば、日本語版が無料で公開されています。 git-scm.com

次回の記事

  terapotan.hatenablog.jp

前回の記事

terapotan.hatenablog.jp

連載記事一覧

terapotan.hatenablog.jp