マージ(Merge)は、Gitにおいて2つの異なる開発ラインからの変更を1つのターゲットブランチに統合するブランチマージ操作です。rebaseとは異なり、mergeは2つの親を持つ特別なマージコミットを作成することで、完全なブランチ履歴を保持します。Git公式ドキュメント(2026年)によると、mergeは履歴を書き換えず、いつどのブランチがマージされたかを追跡できるため、ブランチを統合する最も安全な方法です。main、develop、releaseといったパブリックブランチでのマージにおける標準的な選択肢です。
主要ポイント
マージ(Merge)は、指定されたブランチからの変更を現在のブランチに統合するgit mergeコマンドです。Gitは共通の祖先(ベースコミット)を見つけ、祖先に対する各ブランチの差分を計算し、統合された変更セットを含むマージコミットを作成します。結果として、ターゲットブランチはマージされたブランチからのすべての変更を受け取ります。
構文:ターゲットブランチ(例:main)にいる状態で、git merge featureを実行します。コンフリクトがなければ、Gitは自動的にマージコミットを作成します。デフォルトのマージコミットメッセージは「Merge branch 'feature' into main」です。-mフラグを使用してメッセージを変更するか、開かれたエディタで編集できます。
マージは非破壊操作です。rebaseとは異なり、mergeは既存のコミットに触れません。コミットは同じハッシュ、作者、日付を保持します。これにより、mergeは複数の開発者が同時に作業するブランチをマージする唯一の安全な方法となります。問題が発生した場合は、git merge --abortでマージをキャンセルできます。
# ターゲットブランチに切り替え
git checkout main
# フィーチャーブランチをマージ
git merge feature
# 結果 — 2つの親を持つマージコミット
git log --oneline --graph
# カスタムメッセージでマージ
git merge feature -m "feat: integrate authentication module"
Gitは3つのマージモードをサポートしており、望ましい結果に基づいて選択されます。通常マージ(デフォルト)はマージコミットを作成します。Squashマージはフィーチャーブランチのすべてのコミットを1つに統合します。Fast-forwardは可能な場合、コミットを作成せずにブランチポインタを進めます。モードの選択は、チームのワークフローと履歴ルールに依存します。
通常マージ(--no-ff) — fast-forwardとしてマージできた場合でもマージコミットを作成します。mainブランチに推奨されます。マージコミットはフィーチャーの統合ポイントを明確に示し、1回のマージコミットのrevertでフィーチャーブランチのすべての変更を簡単に元に戻せます。GitHubはPRをマージボタンで統合する際、デフォルトでこのモードを使用します。
Squashマージ(--squash) — フィーチャーブランチのすべてのコミットをターゲットブランチの1つのコミットにまとめます。フィーチャーブランチの草稿履歴をmainに持ち込みたくない場合に便利です。欠点:元のコミットとの関連が失われ、フィーチャーが段階的にどのように開発されたかを見ることができません。GitHubはPRで「Squash and merge」を選択した場合にこのモードを使用します。
Fast-forward(--ff) — フィーチャーブランチが分岐してからターゲットブランチに新しいコミットがない場合、Gitはマージコミットを作成せずにポインタを進めます。履歴は線形のままです。--no-ffフラグはマージコミットを強制し、--ff-onlyはfast-forwardが不可能な場合にエラーになります。
# マージコミットを強制(mainに推奨)
git merge --no-ff feature
# Squashマージ — すべてのコミットを1つに
git merge --squash feature
git commit -m "feat: add authentication"
# Fast-forwardのみ可能な場合
git merge --ff-only feature
# コンフリクトしたマージを中断
git merge --abort
マージ戦略は、Gitが変更を統合するために使用するアルゴリズムを決定します。各戦略は異なるシナリオに適しています。Gitは自動的に適切な戦略を選択しますが、開発者は--strategyフラグを使用して明示的に指定できます。戦略を理解することで、複雑なマージにおけるGitの動作を予測できます。
Recursive — 2つのブランチをマージするためのデフォルト戦略。Gitは共通の祖先を見つけ、各ブランチの変更を計算し、それらをマージします。共通の祖先が見つかった場合、recursiveはファイルの名前変更と追加を正しく処理します。コンフリクト時には、recursiveは追加オプションを使用できます:ours(自動的に私たちのバージョンを選択)とtheirs(相手のバージョンを選択)。
Octopus — 3つ以上のブランチを同時にマージするため:git merge feature1 feature2 feature3。Octopusはコンフリクト解決をサポートしていません — コマンドを呼び出す前にすべてのコンフリクトを解決する必要があります。主に、コンフリクトしないことが保証されている複数の独立したブランチ(例:異なるモジュール)をマージするためにまれに使用されます。
| 戦略 | ブランチ数 | コンフリクト解決 |
|---|---|---|
| Recursive | 2 | 自動 + ours/theirsオプション |
| Octopus | 3+ | なし — すべてのコンフリクトを事前に解決する必要あり |
| Ours | 任意 | 常に私たちのバージョンを選択、相手の変更を無視 |
| Subtree | 2 | サブツリーマージ用 |
Ours — マージされたブランチからの変更を完全に無視し、ターゲットブランチの現在のコンテンツを保持する特別な戦略。マージコミットは作成されますが、コンテンツは変更されません。履歴にマージの事実を記録する必要があるが、実際には他のブランチからのすべての変更を拒否したい場合に便利です。
マージコンフリクトは、ファイルの同じ行が両方のブランチで異なる方法で変更された場合に発生します。Gitは自動的にどちらのバージョンが正しいかを判断できず、マージを一時停止します。コンフリクトは、一方のブランチでファイル名が変更され、もう一方で修正された場合、または同じファイルが同時に削除および修正された場合にも発生する可能性があります。
解決プロセス:Gitはコンフリクトしているファイルにマーカーを付けます。ファイルには<<<<<<< HEAD(私たちのバージョン)、=======(区切り)、>>>>>>> feature(相手のバージョン)のセクションが表示されます。開発者は手動でコンフリクトしているセクションを編集し、両方のバージョンから必要な行を選択し、マーカーを削除し、ファイルを保存して、git addでインデックスに追加します。
視覚的なコンフリクト解決のために、Gitはマージツール(mergetool)をサポートしています — 外部比較ツールです。人気のマージツール:Meld、KDiff3、Beyond Compare、VS Code(組み込みコンフリクトエディタ)。マージツールは3つのパネルを表示します:私たちのバージョン、相手のバージョン、結果。開発者は最終ファイルに含めるコードブロックを視覚的に選択します。
# マージを開始してコンフリクトを検出
git merge feature
# コンフリクト(内容):src/main.swiftでマージコンフリクト
# コンフリクトファイルを確認
git status
# ビジュアルmergetoolを開く
git mergetool
# 解決後 — addとcommit
git add src/main.swift
git commit
# マージを中断
git merge --abort
mergeはrebaseよりも優先されるいくつかの重要な状況があります。1つ目:他の開発者がアクセスできるパブリックブランチで作業する場合。mergeは履歴を書き換えないため、同僚は安全に同期できます。パブリックブランチでrebaseを行うと、分岐した履歴が作成され、すでに古いコミットを持っている全員にコンフリクトが発生します。
2つ目の状況:フィーチャーブランチを完了する場合。ほとんどのチームは、フィーチャーの統合時点を記録するために、mainへのmerge(--no-ffフラグ付き)を好みます。これにより、履歴のナビゲーションが簡素化され、マージコミットを1回git revertするだけでフィーチャー全体を簡単に元に戻せます。GitHub Flowはデフォルトで3つのマージオプションを提供しています:単純マージ、squashマージ、rebaseマージ。
3つ目の状況:レビュー済みのプルリクエストを扱う場合。GitHubとGitLabは、異なるオプションを持つマージボタンを提供しています。Merge(Create a merge commit)— マージコミットを含む完全な履歴。Squash and merge — 開発詳細のないクリーンな履歴。Rebase and merge — マージコミットなしの線形履歴ですが、コミットの書き換えを伴います。選択はチームのルールに依存します。
第一のルール:マージ前には常にターゲットブランチの最新バージョンを使用します。フィーチャーブランチをマージする前に、git checkout main && git pullを実行します。これによりコンフリクトが最小限に抑えられ、マージコミットにすべての最新の変更が含まれることが保証されます。ターゲットブランチが大幅に進んでいる場合は、最初にフィーチャーブランチ内でgit merge mainを実行して、そのコンテキストでコンフリクトを解決します。
第二のルール:マージ後にコードをテストします。コンフリクトがなくても、マージによって動作が変わる可能性があります。CI/CDパイプラインは、プロダクションに送信する前にマージコミットでテストを実行する必要があります。一部のチームはマージゲートを使用しています — 合格するまでマージをブロックする必須チェックです。
第三のルール:マージコミットを文書化します。標準メッセージ「Merge branch 'feature' into main」はあまり有用ではありません。何がマージされたかの説明を追加することをお勧めします:「Merge authentication module: login, registration, password recovery」。これにより、履歴分析と回帰の検索が簡素化されます。大規模プロジェクトでは、マージコミットはPRのタイトルから自動生成されます。
よくある質問
マージするとは、あるブランチから別のブランチに変更を統合するためにgit mergeを実行することを意味します。結果は、マージイベントを記録し、両方のブランチからの変更を含むマージコミットです。これはGit Flowにおいて、フィーチャーブランチをmain、develop、またはreleaseに統合する主要な方法です。
Squashマージはフィーチャーブランチのすべてのコミットをターゲットブランチの1つのコミットに統合し、中間開発履歴を失います。通常マージはすべてのフィーチャーブランチのコミットを保持しながらマージコミットを作成します。Squashマージはクリーンな履歴を提供しますが、フィーチャーの段階的な開発を追跡することはできません。
コンフリクトしているファイルを開き、<<<<<<< HEADと>>>>>>>のマーカーがあるセクションを見つけます。内容を編集し、両方のバージョンから必要な行を残してマーカーを削除します。ファイルを保存し、git addとgit commitを実行します。視覚的な解決にはgit mergetoolを使用できます。
Mergeは常にパブリックブランチ(main、develop、release)に使用されます。履歴を書き換えないからです。Rebaseは公開前の個人のフィーチャーブランチに適用されます。ブランチが共有リポジトリの一部となり、同僚がアクセスした後は、mergeのみが許可されます。
マージ完了前(コンフリクト中) — git merge --abortでマージを完全にキャンセル。完了後 — git revert <merge-commit-hash> -m 1で取り消しコミットを作成。-m 1フラグは保持する親ブランチ(ターゲット)を指定します。公開ブランチの場合、git revertはgit resetよりも安全です。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。