皆さん、こんにちは!
エンジニアアイドル「ハックガールズ」の堤沙也と濱ヶ崎美季です。
私たちと一緒にGitを学ぶこの連載も、いよいよ今回で最終回となりました。最終回はGitの醍醐味である複数人での共同開発時に欠かせないブランチを活用した開発について紹介します!
ブランチの意義
ブランチは、個人で開発をする時にも、複数人で共同開発する時にも活用できます。たとえば複数の機能を平行して開発したい場合。
- 上司:
- 来月頭までに機能Aと機能Bをリリースする!
- あなた:
- 了解です。機能Aをリリースしたあとに、機能Bの開発に着手すれば良いですか?
- 上司:
- それが、取引先の要望次第で、機能Bのリリースだけが先になるかもしれないんだ……。同時に下準備だけ進めておいてくれないか。
- あなた:
- !
すなわち、機能Aと機能Bの開発を同時に進めたいが、どちらを先にリリースするかはまだ未定。1つのリポジトリに対して開発する機能ですが、各々影響を与えあわない状況下で同時に開発を進めたい、といった要件で活躍します。
このとき、機能Aと機能Bを開発しているのが個人であっても、機能AをAさんが開発して、機能BをBさんが開発するという複数人での開発であっても、ブランチを分けて開発を進めれば良いということです。
masterブランチという現実世界に対して、別のブランチという、複数のパラレルワールドを作るイメージです。
今回紹介する、ブランチに関するgitコマンドは下記の通りです。
- git branch
- git fetch
- git rebase
- git merge
- git pull
1つ1つ見て行きましょう!
ブランチの作成
git branch
機能Aの開発用ブランチを作成したい場合は、下記のコマンドで作成することができます。
git fetch
また、git fetchで、リモートリポジトリの最新の履歴を現在の作業ディレクトリに取得することができます。
たとえば、共同開発チームのAさんがAブランチをリモートリポジトリにpushしていたとします。そのとき
で、Aブランチが自分の作業ディレクトリで扱えるようになります。
ブランチの確認
引数なしで、
と実行すると、現在の作業ディレクトリに存在するブランチを確認することができます。デフォルトの状態ではmasterブランチというブランチのみが存在する状態になっていますが、作成したブランチが別にあれば、その一覧が表示されます。接頭にアスタリスクが付いているブランチが、現在のブランチです。
また、直前で紹介した git fetchでリモートリポジトリから取得したブランチを確認するには、
を実行します。このとき、「remote/origin/branch名」といった remoteという接頭辞付きで表示されているブランチがリモートリポジトリから取得したブランチです。
変更の取り込み
リモートリポジトリから取得したブランチの変更を自分の作業ディレクトリのブランチに取り込みたい場合、もしくは自身の作業ディレクトリ内で作業用のブランチの変更をmasterブランチなど、別のブランチに合流させたい場合など、ブランチの統合を行うには、大きく分けて2つの方法があります。
それがrebaseとmergeです。
git rebase
今回は作業用のfeat/Aブランチをmasterブランチに統合したいとします。コマンドは、
です。
このとき、仮にfeat/Aブランチの分岐元が、masterの最新commitよりも古い場所だったとしても、feat/Aブランチの分岐元がmasterブランチの最新のコミットへ移動します。これがgit rebaseの特徴です。
git merge
rebaseと似て非なる統合コマンドがmergeです。
rebaseとの違いは、仮にfeat/Aブランチの分岐元が、masterの最新commitよりも古い場所だった場合、mergeコミットと呼ばれる「ブランチを統合した記録」のcommitが新たに作成されるということです。
すなわち、「Merge branch ‘feat/A'」といったメッセージがついた commitが作成されるため、feat/Aブランチという別のブランチがmasterにこのタイミングで統合されたことが明示的に記録に残ることになります。
ただし、feat/Aブランチの分岐元がmasterの最新commitだった場合は、オプションを付けない限りmergeコミットは作られません。
明示的にmergeの記録を残したい場合は、
とオプション付きでmergeするようにしましょう。
conflictの解消
なお、rebase, mergeともに実行すると競合状態になる場合があります。競合とは、統合元のブランチと統合先のブランチでまったく同じファイルの、まったく同じ行を更新してしまった場合などに発生するもので、conflictと呼びます。
といったメッセージが現れたら、conflictを解消する必要があります。
対象ファイルを開くと、ファイル内に
といった表記がある部分があります。
これは、
HEAD(統合先の最新状態)で「ほげほげほげ」と更新されていた部分をfeat/Aでは「ふがふがふが」と更新していますが、最終的にはどちらを活かしますか?
と聞かれている状態です。ここで残したい変更以外を消してファイルを保存し直してから、
を実行すれば、conflictの解消ができます。
git pull
なお、リモートのブランチの変更を反映するのによく使われるコマンド「git pull」は「git fetch+git merge」と同じ挙動をします。
と
は同じものです。rebaseとmergeどちらが適切かは、プロジェクトの方針や状況によって異なるので、チームで相談して方針を決めておくと良いですね。