こんにちは、かつコーチです。
前回はgit branch・git switchを使って、ブランチを作成・切り替える方法を解説しました。
トピックブランチで機能を作り終えたら、次にやることは1つです。
その内容をmainブランチに取り込む「マージ」です。
今回はgit mergeの基本的な使い方を、実際の手順に沿って見ていきましょう。
git mergeとは
2つの下書きを1つにまとめるイメージ
マージとは、2つの下書きを1つの原稿にまとめる作業だとイメージしてください。
mainという清書用の紙と、feature-loginという実験用の下書きがあったとします。
下書きの内容を確認し、問題なければ、その内容を清書の紙に書き写して1つにまとめる。
これがgit mergeがやっていることです。
Gitの内部では、2つのブランチのコミット履歴を比較し、両方の変更を反映した新しい状態を作り出しています。
マージが必要になる場面
マージが必要になるのは、主に次のような場面です。
- トピックブランチで作った機能が完成し、mainに取り込みたいとき
- チームメンバーが作業したブランチを、自分のブランチに取り込みたいとき
- リリース用のブランチに、複数の修正をまとめたいとき
「ブランチで自由に実験し、完成したらマージで本線に合流させる」という流れが、Gitを使った開発の基本サイクルです。
git mergeの基本的な使い方
手順:ブランチ作成→編集→mainに戻ってmerge
具体的な手順を、コマンドとともに確認していきます。
# 1. mainから新しいブランチを作って作業する
git switch -c feature-login
echo "ログイン機能" >> feature.txt
git add feature.txt
git commit -m "ログイン機能を追加"
# 2. mainブランチに戻る
git switch main
# 3. feature-loginの内容をmainに取り込む
git merge feature-login
ポイントは、マージ先のブランチに切り替えてからgit mergeを実行することです。
「feature-loginをmainに取り込みたい」のに、feature-loginブランチにいる状態でgit merge mainと打ってしまうと、逆方向のマージになってしまうので注意しましょう。
Fast-forwardマージ
mainブランチが分岐した後に一切更新されていない場合、Gitは新しいコミットを作らず、単純にブランチの位置を進めるだけで済ませます。
これをFast-forward(早送り)マージと呼びます。
main: A---B
\
feature-login: C---D
↓ merge後(Fast-forward)
main: A---B---C---D
履歴が一直線になるので、非常にシンプルな状態です。
3-way merge(マージコミットが作られるケース)
一方、mainブランチ側でも別のコミットが進んでいた場合は、Fast-forwardできません。
その場合Gitは、両方の変更を取り込んだマージコミットを新しく作成します。
main: A---B---------E
\ /
feature-login: C---D--
このEが、2つの下書きを1つにまとめた「マージコミット」です。
コミットメッセージには、デフォルトでMerge branch 'feature-login'のような内容が自動的に入ります。
マージの結果を確認する
git logでマージコミットを確認する
マージが正しく行われたかは、git logで確認できます。
git log --oneline --graph
* e5f6g7h Merge branch 'feature-login'
|\
| * d4e5f6g ログイン機能を追加
* | b2c3d4e READMEを更新
|/
* a1b2c3d 初期コミット
--graphオプションを付けると、ブランチが分岐して合流した様子が線で可視化されるので、状況を把握しやすくなります。
–no-ffオプションで意図的にマージコミットを残す
Fast-forwardできる状況でも、あえてマージコミットを残したい場合は--no-ffオプションを使います。
git merge --no-ff feature-login
「このタイミングでfeature-loginの機能が合流した」という履歴を明示的に残せるため、チーム開発では--no-ffを標準運用にしているプロジェクトも少なくありません。
よくあるつまずきポイント
マージ先のブランチを間違える
私が実際にやってしまった失敗が、マージ先のブランチを勘違いしたまま作業してしまったことです。
❌ Before:feature-loginにいるままmainをマージしようとする
# 本当はfeature-loginの内容をmainに入れたいのに…
git switch feature-login
git merge main
これを実行すると、mainの内容がfeature-login側に取り込まれるだけで、mainブランチには何の変化も起きません。
「マージしたはずなのに、mainに反映されていない」と焦ってgit logを何度も確認した記憶があります。
✅ After:取り込み先のブランチに切り替えてからmergeする
# mainにfeature-loginの内容を取り込みたい
git switch main
git merge feature-login
マージの主語は常に「今いるブランチに、指定したブランチを取り込む」だと意識しておくと、この勘違いを防げます。
マージ後にpushし忘れて反映されない
もう1つ多いのが、ローカルではマージが完了しているのに、リモートリポジトリへの反映(git push)を忘れてしまうケースです。
git switch main
git merge feature-login
git push origin main # これを忘れると、他のメンバーには反映されない
マージはあくまでローカルリポジトリ内での作業なので、チームで共有するには必ずpushまで実行する必要があります。
応用・一歩先の使い方
コンフリクトが起きたら
同じファイルの同じ箇所を、mainとfeature-login側の両方で書き換えていた場合、Gitは自動でマージできず「コンフリクト(衝突)」が発生します。
コンフリクトの読み解き方と解決方法は、次の記事で詳しく解説します。
git merge –abortで中断する
マージ中にコンフリクトが起きて混乱してしまった場合、いったんマージ前の状態に戻すこともできます。
git merge --abort
「とりあえずマージを始めてしまったが、落ち着いてから対応したい」というときの避難コマンドとして覚えておくと安心です。
まとめ
この記事のポイント
git mergeは2つのブランチの変更を1つにまとめる、いわば「2つの下書きの合流作業」- マージは「取り込み先のブランチ」に切り替えてから実行する
- 分岐後にmainが更新されていなければFast-forward、更新されていれば3-way mergeでマージコミットが作られる
--no-ffオプションで、意図的にマージコミットを残す運用もできる- ローカルでマージしただけでは反映されず、
git pushまで必要
次に読むべき記事
マージの基本が分かったら、次は避けて通れない「コンフリクト」の解決方法を押さえておきましょう。
→ 次の記事:コンフリクトの解決方法:同じ場所を書き換えてしまったとき
タグ: Git, 中級者向け, ブランチ