ブランチとマージ
ブランチは履歴を枝分かれさせる仕組みで、本流に影響を与えずに新機能や修正を試せます。git branch で一覧や作成を行い、git switch(または git checkout)で作業対象を切り替えます。枝で仕上げた変更は git merge で元のブランチに取り込みます。いまどの枝にいるかは HEAD という印が指し示しており、切り替えると HEAD の指す先が動きます。
新機能を試したいが、本流を壊すのは怖い。そんなときに使うのがブランチ(git-branch)だ。履歴を枝分かれさせる仕組みである。
本流(多くの場合 main という名前の枝)を壊さないまま、別の枝で新機能の開発や実験を進め、うまくいったら本流に合流させる。この合流がマージ(git-merge)だ。
なぜ枝を分けるのか。開発途中の不安定な状態を本流に混ぜずに済むからだ。たとえば新機能を作っている最中に、本流に対して急ぎの不具合修正が必要になっても、枝が分かれていればお互いに干渉しない。
Git のブランチは内部的には「あるコミットを指す軽い目印」にすぎない。だから作るのも切り替えるのも一瞬で、気軽に何本でも分けられるのが大きな特徴だ。
🌱 枝を作って乗り移る
現在のブランチの一覧は git branch で確認する。実行すると枝の名前が並び、いま自分がいる枝には先頭に * が付く。
新しい枝を作ってそこへ移動するには git switch -c <名前> を使う。-c は create(作成)の意味だ。たとえば git switch -c feature と打つと feature という枝が作られ、同時にそこへ移動する。移動後にもう一度 git branch を打つと、* が feature に移っているのが分かる。
元の枝へ戻るときは -c を付けずに git switch main とする。
なお、以前は同じことを git checkout -b feature と書いていた。今でも checkout は使えるが、「枝の切り替え」と「ファイルの復元」という別々の役割を1つに抱えていて紛らわしかった。そのため、目的別に分かれた git switch が現在の推奨だ。古い資料では checkout が出てくるので、読み替えられるようにしておくと安心だ。
🎯 切り替えるとき内部で何が起きるか
いま自分がどの枝にいるかは、HEAD(git-head)という印が指し示している。HEAD は「現在の作業位置」を表す矢印で、ふだんは今いるブランチの先頭のコミットを指している。
git switch で枝を切り替えると、この HEAD の指す先が移動する。それに合わせて作業ツリーの中身も、切り替えた枝の状態に入れ替わる。
つまり枝を切り替えるとは、HEAD を別の枝へ向け直すことだ。そう考えると、頭の中で整理しやすくなる。
🔀 枝を本流へ戻すマージ
枝の上で git add と git commit を重ねて作業を仕上げたら、本流に戻ってから取り込む。
具体的な流れはこうだ。feature 上で echo 'feature work' > feature.txt のように作業し、git add feature.txt、git commit -m 'Add feature file' でコミットする。そのうえで git switch main で本流へ移り、git merge feature と打って feature の成果を取り込む。
このとき、本流側に枝を分けたあとの新しいコミットが無ければ、Git は本流の目印を枝の先頭までスッと進めるだけで合流が完了する。これを fast-forward(早送り)と呼び、「Fast-forward」と表示され、新しいコミットは作られない。
一方、本流と枝の両方がそれぞれ別々にコミットを進めていた場合は早送りできない。Git は両者を突き合わせて1つの「マージコミット」を新たに作る。これは共通の祖先・本流の先端・枝の先端という3点を見比べて統合するため、3-way merge(3方向マージ)と呼ばれる。
⚡ 衝突したらどうするか
マージで初学者が身構えるのがコンフリクト(衝突)だ。これは、2つの枝で同じファイルの同じ行を別々の内容に書き換えていたときに起こる。
Git はどちらを採用すべきか自分では判断できない。だから勝手に決めずに印を付けて人間に委ねる。
マージを実行すると「CONFLICT」と表示され、「fix conflicts and then commit the result(衝突を直してからコミットせよ)」という案内が出る。
衝突したファイルを開くと、Git が印を書き込んでいる。<<<<<<< HEAD から ======= までが今いる枝側の内容、======= から >>>>>>> までが取り込もうとした枝側の内容だ。
🧩 衝突を解決する手順
印が書き込まれたファイルの解決手順は、あわてなければ簡単だ。
エディタでそのファイルを開き、<<<<<<<・=======・>>>>>>> の3種類の印と、不要なほうの内容を削って、残したい最終形だけにする。
あとは git add でそのファイルを載せ、git commit で確定すればマージ完了だ。最後に git status を打ち、「nothing to commit, working tree clean」と出れば解決できている。
ここで最も多い失敗が、======= などの印を消し忘れて、そのままコミットしてしまうことだ。3種類の印は必ず全部消すこと、そして今どのファイルが衝突中かは git status が「Unmerged paths」として教えてくれること。この2点を覚えておけば落ち着いて対処できる。
🛠 実務ではどう回すのか
実務では、「1つの作業につき1本の枝」を基本にすると見通しが良くなる。
新機能なら feature-login、不具合修正なら fix-crash のように、何の作業かが分かる名前で枝を切る。その枝で作業し終えたら本流へマージし、不要になった枝は片付ける。この流れを繰り返す。
本流を常に「動く状態」に保ったまま、危なっかしい作業は枝の上で完結させられる。これがブランチを使う最大の利点だ。
複数人で開発するときはこの恩恵がいっそう大きい。各自が自分の枝で並行して進め、できたものを順にマージしていくのが、現代的な開発の基本形になっている。
まずはひとりでも、機能ごとに枝を分けて作業する練習から始めると、マージとコンフリクトの感覚が自然に身につく。