GIT VISUALIZER

git merge

2つのブランチの変更を統合し、マージコミットを作成するコマンドです。

初期状態
分岐した状態を確認
main ブランチと feature ブランチが C2 から分岐しています。main には C3, C4 が、feature には F1, F2 が追加されています。
ステップ制御
進捗1 / 3
グラフ情報
ブランチ数2
コミット数6
HEADfeature
操作Merge
COMMIT GRAPHSTEP 1
CODE VIEWapp.js
main (C4)
function greet(name) {
return "Hello, " + name;
}
 
// C3: バグ修正
function validate(input) {
if (!input) return false;
return true;
}
 
// C4: ドキュメント更新
// Version: 2.0
feature (F2)
function greet(name) {
return "Hello, " + name;
}
 
// F1: 新機能追加
function newFeature() {
return "awesome";
}
 
// F2: 機能を改善
function newFeature(opt) {
return opt || "awesome";
}
main ブランチ
feature ブランチ
マージコミット
MERGE ステップログ
1分岐した状態を確認
2git merge feature を実行
3マージコミット M を作成 → 完了
解説

📌
Merge とは

git merge は、2つのブランチの変更を1つに統合するコマンドです。 たとえば feature ブランチで新機能を開発したあと、その変更を main ブランチに取り込むときに使います。

マージを実行すると、Git は自動的に「どこで枝分かれしたか(マージベース)」を見つけ、 両方のブランチの変更を比較して統合します。上のツールでは C2 が分岐点で、C4(main の変更)と F2(feature の変更)を統合して緑色の M(マージコミット)を作っています。

マージの最大の特徴は非破壊的なこと。既存のコミットは一切変更されず、新しいマージコミットが追加されるだけです。 間違えても git reset ですぐに元に戻せるため、初心者でも安全に使えます

🔀
Merge の種類

Fast-forward Merge
分岐後に main に新しいコミットがない場合に発生します。マージコミットを作らず、main のポインタを feature の先端まで進めるだけです。 履歴が一直線になるため最もシンプルですが、「マージした」という記録は残りません。
git merge [ブランチ名]main に新コミットがなければ自動的に ff になる
C2F1F2main →
3-way Merge(今回の対象)
上のツールで可視化しているのがこれです。main にも feature にも新しいコミットがある場合、 Git は「マージベース(共通の祖先)」「main の最新」「feature の最新」の3つを比較して自動統合します。 結果としてマージコミット(M)が作られ、履歴に分岐の形が残ります。
git merge [ブランチ名]両方にコミットがあると自動的に 3-way になる
baseC4F2M
Squash Merge
feature のコミットを1つにまとめて main に追加します。マージコミットも作られません。 「WIP」「fix typo」のような細かいコミットを1つのきれいなコミットに整理したいときに便利です。 ただし feature の個々のコミット履歴は main から見えなくなります。
git merge --squash [ブランチ名]ステージングに追加されるだけなので、その後 git commit が必要
F1F2F3S1コミットに
No-ff Merge(--no-ff)
fast-forward できる状況でも強制的にマージコミットを作るオプションです。 「この feature をいつマージしたか」を履歴に残したいときに使います。 GitFlow では --no-ff を推奨しています。
git merge --no-ff [ブランチ名]
C2F1F2Mmain

💻
コマンドとオプション

git merge [ブランチ名]feature ブランチを現在のブランチにマージする(最も基本的な使い方)
git merge --no-ff [ブランチ名]fast-forward できる場合でもマージコミットを強制的に作成する
git merge --squash [ブランチ名]feature の変更をステージングに追加するだけ(コミットは自分で行う)。履歴が1コミットにまとまる
git merge --abortコンフリクト発生中のマージを中止し、マージ前の状態に完全に戻す
git merge --continueコンフリクトを解決した後、マージを続行してマージコミットを作成する
git merge --no-commit [ブランチ名]マージは実行するがコミットはしない。マージ結果を確認してから手動でコミットしたいときに使う

⚠️
コンフリクトの解消

同じファイルの同じ行を両方のブランチが変更していると、Git は自動統合できずコンフリクトが発生します。 上のツールでは異なる関数を変更しているためコンフリクトは起きませんが、実際の開発ではよく遭遇します。

コンフリクトマーカーの読み方
function greet(name) {
<<<<<<< HEAD (main)
  return "Hi, " + name;
=======
  return "Hello, " + name + "!";
>>>>>>> feature
}
<<<<<<< HEADここから「現在のブランチ(main)の変更」が始まる
=======区切り線。ここから「取り込もうとしているブランチの変更」が始まる
>>>>>>> feature「feature ブランチの変更」がここで終わる
解消手順
1
コンフリクトが起きたファイルを開き、マーカー(<<<, ===, >>>)を確認する
2
残したいコードを選ぶ(片方を採用するか、両方を組み合わせるか自分で判断する)
3
マーカー行(<<<, ===, >>>)をすべて削除する
4
git add で解決済みファイルをステージング → git merge --continue でマージを完了
途中でやめたくなったら:git merge --abort でマージ前の状態に完全に戻せます。安心して試してください。

⚖️
Merge vs Rebase

MergeRebase
履歴分岐が残る(ダイヤモンド形)一直線になる
既存コミット変更しない(安全)ハッシュが変わる(注意)
コンフリクト1回で解決コミットごとに発生する可能性
取り消しgit revert -m 1 で簡単git reflog で探す必要あり
共有ブランチ安全に使える使ってはいけない
どちらを使うべき?
  • merge を使う場面:PR をマージするとき、共有ブランチの統合、チームで作業するとき。迷ったら merge が安全です。
  • 📐rebase を使う場面:ローカルの feature ブランチで main の最新に追従するとき。push 前のコミット整理。きれいな履歴を重視するチーム。

🔧
よくある失敗と対処法

間違えてマージしてしまった
まだ push していないなら、マージコミットを取り消すのが最も簡単です。
# マージコミットを取り消す(push 前)
git reset --hard HEAD~1

# すでに push した場合(履歴を書き換えずに打ち消す)
git revert -m 1 HEAD
-m 1 は「1番目の親(main 側)を残す」という意味です。マージコミットには親が2つあるため、どちらを残すか指定する必要があります。
間違ったブランチにマージしてしまった
main にマージするつもりが develop にマージしてしまった、など。push していなければ reset で戻せます。
# マージ前の状態に戻す
git reset --hard HEAD~1

# 正しいブランチに切り替えてやり直す
git checkout main
git merge [ブランチ名]
コンフリクトがたくさんあってパニック
コンフリクトの解消に自信がないときは、いったん中止して仕切り直すのが安全です。
# マージを中止(元の状態に完全に戻る)
git merge --abort

# コンフリクト時に相手の変更を丸ごと採用したい場合
git checkout --theirs <file>
git add <file>

関連コンテンツ