技術資料

GitのコンフリクトをVS Codeで解消する:PHPのサンプルで再現からテストまで

作成日:2026.10.22

GitHubのPull Requestで発生するコンフリクトを、PHPの小さな送料計算で再現します。mergeの基本から、VS Codeで両方の変更意図を反映する修正、テスト、同じPull Requestへの反映、作業を中止する方法までを解説します。

Pull Requestをmergeしようとしたら、コンフリクトが表示されて先に進めない。GitHubを使い始めた頃は、ここで手が止まりやすいかと思います。

コンフリクトの解消では、競合の表示を消すだけでなく、両方の変更で実現したかったことを残す必要があります。今回は小さなPHPの送料計算を例に、GitHubでの競合確認から、VS Codeでの修正、テスト、中止する方法までを整理します。

ブランチ、commit、push、Pull Requestの基本は、GitHub入門の記事を参照してください。

コンフリクトとは

merge(マージ)は、別のブランチで加えた変更を、現在のブランチへ取り込む操作です。例えば、作業ブランチで完成した変更をmainへ取り込むときに使います。

Gitは、二つのブランチの変更を比べて、自動で統合できる部分を取り込みます。ただし、同じ行を別々の内容へ変更した場合などは、どちらを残すか判断できず、mergeが途中で止まることがあります。これがコンフリクトです。

GitHubのPull Requestでも、取り込み先と作業ブランチの間に競合があると、そのままmergeできません。ファイルの削除と編集がぶつかる場合などもありますが、この記事では同じ行を変更した場合に絞ります。

例えば、元の処理が「送料は一律500円」だったとします。

ブランチ変更内容変更の意図
main3,000円以上なら送料0円、それ以外は500円送料無料の条件を追加したい
feature/shipping-fee送料を一律600円へ変更通常送料を改定したい

どちらの変更も必要なら、最終的な処理は「3,000円以上なら送料0円、それ以外は600円」です。片方のコードをそのまま選ぶだけでは、もう片方の意図が失われます。

今回の環境と作業の流れ

WindowsのVS Codeでファイルを編集し、ブランチの切り替えやmergeには統合ターミナルのPowerShellを使います。表示名はバージョンや表示言語によって異なることがあります。

今回は、作業ブランチへmainの変更を取り込んで競合を解消し、その結果を同じPull Requestへ反映します。mainへ作業ブランチを取り込む操作は、最後のレビュー後です。

共通の状態:送料500円
  ├─ main:3,000円以上を送料無料にする
  └─ feature/shipping-fee:通常送料を600円にする
       ↑ mainの変更をここへ取り込み、競合を解消する

検証には専用の練習用リポジトリを使ってください。再現のためmainも直接更新するので、実際の業務リポジトリでは試さないようにします。また、GitとPHPのコマンド、GitHubへpushできる認証が使える前提です。

サンプルコードで競合を再現する

元になる送料計算を保存する

GitHubでREADME付きの練習用リポジトリを作り、mainブランチがある状態でcloneします。次のURLは、自分の練習用リポジトリに置き換えてください。

git clone https://github.com/OWNER/merge-conflict-demo.git
cd merge-conflict-demo
git switch main
git status

VS Codeでこのフォルダーを開き、shipping.phpを作成します。PHPファイルはUTF-8で保存してください。

<?php
declare(strict_types=1);

function shippingFee(int $subtotal): int
{
    return 500;
}

小計を受け取り、送料を整数で返すだけの関数です。小計は0円以上の整数が渡る前提とし、入力チェックや税計算は省略します。

git add shipping.php
git commit -m "送料計算のサンプルを追加"
git push origin main

ここから二つのブランチに分けて、同じ行を変更してみます。

作業ブランチでは送料を600円にする
git switch -c feature/shipping-fee

VS Codeでshipping.phpのreturn文を変更します。

    return 600;

保存してから、この変更をcommit・pushします。

git add shipping.php
git commit -m "通常送料を600円に変更"
git push -u origin feature/shipping-fee
mainでは送料無料の条件を追加する
git switch main

mainへ切り替えると、return文は元の500円へ戻ります。今度は、同じ行を次のように変更します。

    return $subtotal >= 3000 ? 0 : 500;

三項演算子で、小計が3,000円以上なら0円、それ以外なら500円を返します。

git add shipping.php
git commit -m "3000円以上を送料無料にする"
git push origin main
git switch feature/shipping-fee

これで、共通の500円という処理から、別々の変更が分かれた状態になりました。

GitHubのPull Requestで競合を確認する

GitHubで練習用リポジトリの「Pull requests」から「New pull request」を開きます。ブランチは次の向きにします。

  • base:main。最終的に変更を取り込む先
  • compare:feature/shipping-fee。今回の作業ブランチ

競合があってもPull Requestは作成できます。「通常送料を600円に変更」のようなタイトルで作成し、mergeに関する欄を確認します。shipping.phpの競合解消を求める案内が表示され、そのままではmergeできない状態になります。

単純な競合はGitHub上でも修正できますが、今回はPHPの実行結果まで確認したいので、ローカルのVS Codeで解消します。手順の考え方は、GitHub公式のコンフリクトの説明でも確認できます。

作業ブランチへmainを取り込む

VS Codeへ戻り、作業ブランチにいることと、未commitの変更がないことを確認します。

git switch feature/shipping-fee
git status
git fetch origin
git merge origin/main

fetchはGitHub側の変更を取得する操作です。取得したmainの状態を表すorigin/mainを、現在の作業ブランチへmergeしています。ローカルのmainを更新し忘れていても、fetchした取り込み先の内容を指定できます。

今回の例では、次のように競合して途中で止まります。

Auto-merging shipping.php
CONFLICT (content): Merge conflict in shipping.php
Automatic merge failed; fix conflicts and then commit the result.

これは、競合箇所の修正を待っている状態です。もう一度mergeしたり、別のブランチへ切り替えたりせず、まずgit statusで対象を確認します。

git status

shipping.phpが両方のブランチで変更されたファイルとして表示されます。VS Codeのソース管理では、競合中のファイルを「Merge Changes」から開きます。

VS Codeで両方の変更意図を反映する

CurrentとIncomingを確認する

通常のテキスト表示では、競合箇所に次のようなマーカーが入ります。Gitの競合表示設定によっては、共通の変更前の内容も追加表示されます。

function shippingFee(int $subtotal): int
{
<<<<<<< HEAD
    return 600;
=======
    return $subtotal >= 3000 ? 0 : 500;
>>>>>>> origin/main
}

今回はfeature/shipping-fee上でorigin/mainをmergeしているので、対応は次のとおりです。

表示今回の内容
Current/HEAD作業ブランチの「送料600円」
Incoming/origin/mainmainの「3,000円以上は送料無料」

Currentが常に「自分の変更」、Incomingが常に「他人の変更」という意味ではありません。特にrebaseでは対応が異なるので、名前だけで選ばず、今行っている操作とコードの内容を確認します。

片方を選ぶだけでは足りない場合は手で直す

VS Codeには、Currentを残す、Incomingを残す、両方を残す、といった選択肢があります。ただ、今回の例ではどれかを押すだけでは完成しません。

Currentだけなら送料無料の条件が消え、Incomingだけなら通常送料が500円へ戻ります。両方をそのまま並べても、最初のreturnで処理が終わってしまいます。

そこで、shipping.phpを次の内容へ修正します。競合マーカーも削除してください。

<?php
declare(strict_types=1);

function shippingFee(int $subtotal): int
{
    return $subtotal >= 3000 ? 0 : 600;
}

これで「送料無料の条件」と「600円への改定」の両方が残ります。

並べて確認したい場合は、競合ファイルを右クリックして「Open in Merge Editor」を開き、Result欄を編集する方法もあります。「Complete Merge」はそのファイルをステージする操作で、リポジトリ全体のmergeをcommitまで完了する操作ではありません。詳しくは、VS Code公式の競合解消手順を参照してください。

境界値をテストしてからcommitする

競合マーカーが消えても、処理が正しいとは限りません。今回は3,000円の前後を含めて、次の結果になることを確認します。

小計期待する送料
2,999円600円
3,000円0円
5,000円0円

同じフォルダーにcheck-shipping.phpを作ります。

<?php
declare(strict_types=1);

require __DIR__ . '/shipping.php';

$cases = [
    [2999, 600],
    [3000, 0],
    [5000, 0],
];

$failed = false;
foreach ($cases as [$subtotal, $expected]) {
    $actual = shippingFee($subtotal);
    if ($actual !== $expected) {
        printf("FAIL: subtotal=%d expected=%d actual=%d\n", $subtotal, $expected, $actual);
        $failed = true;
    } else {
        printf("OK: subtotal=%d shipping=%d\n", $subtotal, $actual);
    }
}
exit($failed ? 1 : 0);

統合ターミナルから、構文と結果を確認します。

php -l shipping.php
php -l check-shipping.php
php check-shipping.php
OK: subtotal=2999 shipping=600
OK: subtotal=3000 shipping=0
OK: subtotal=5000 shipping=0

例えばreturn文をreturn 600;だけにすると、3,000円と5,000円のケースがFAILになります。送料無料の条件だけ残して通常送料を500円にすると、2,999円のケースがFAILになります。こうして両方の意図を確認できるようにしておくと、修正の漏れを見つけやすくなります。

VS Codeのソース管理でshipping.phpと新しく作ったcheck-shipping.phpをステージし、差分を確認します。ターミナルなら次の操作です。

git add shipping.php check-shipping.php
git diff --cached
git diff --cached --check
git status

この例では、ステージされた差分に意図した送料計算と確認コードが入り、未解消のファイルが残っていないことを確認します。--checkは競合マーカーの混入などを調べられますが、送料の仕様が正しいかまでは判定しません。

問題がなければ、VS Codeのソース管理でメッセージを入力してcommitします。ターミナルで行う場合は次のとおりです。

git commit -m "送料無料条件と改定送料を両立して競合を解消"
git status
git push origin feature/shipping-fee

merge途中という表示が消え、今回の例では未commitの変更も残っていなければ、ローカルの解消作業は完了です。

同じPull Requestで解消結果を確認する

GitHubのPull Requestを開き直します。同じ作業ブランチへpushしたので、Pull Requestを作り直す必要はありません。

  • 競合の解消を求める案内が消えたか
  • 「Files changed」で、通常送料600円と送料無料の条件が両立しているか
  • 確認コードが意図どおり追加されているか
  • CIがある場合は、テストなどのチェックが成功したか

mainには既に送料無料の変更があるため、mainとの差分にその変更が新規追加として出ないこと自体は問題ありません。最終的なファイルの内容も見て判断します。

競合が解消しても、レビュー承認やCI、ブランチ保護の条件が残っていれば、すぐにmergeできるとは限りません。また、確認中にmainへ別の変更が入ると、再び競合することもあります。差分とチェック結果を確認してから、通常のレビュー・mergeへ進みます。

解消作業を中止したいとき

両方の変更意図が分からない、別の担当者へ確認したい、といった場合は、無理に片方を選ばず中止して構いません。ここで扱うのは、競合で止まった後、mergeのcommitをまだ作っていない段階です。

途中の修正を残したい場合は、先に必要な内容をリポジトリ外のメモなどへ控えておきます。その後、統合ターミナルで実行します。

git status
git merge --abort
git status

今回のように未commitの変更がない状態から始めた例では、merge前の作業ブランチの内容へ戻り、途中の競合解消作業は取り消されます。新しく作った未追跡ファイルまで削除する操作ではないので、check-shipping.phpなどを作成済みなら、その扱いは別途確認します。

Git公式のgit mergeの説明にもあるように、開始前から未commitの変更がある場合は、完全に元へ戻せないことがあります。作業前の状態確認が大切です。また、既にcommit・pushした変更を取り消す操作とは異なります。

まとめ

コンフリクトでは、どちらのコードを残すかより先に、両方の変更の目的を確認します。今回なら、送料無料の条件を残しつつ、通常送料を600円へ変更するのが必要な修正でした。

競合の表示を消した後も、差分とテスト結果を確認し、同じPull Requestへpushしてから再度レビューします。判断材料が足りない場合は、mergeを中止して確認する方法も覚えておくと安心です。

この記事を書いた人

※上が私です。

奈良市を拠点に、27年以上の経験を持つフリーランスWebエンジニア、阿部辰也です。

これまで、ECサイトのバックエンド開発や業務効率化システム、公共施設の予約システムなど、多彩なプロジェクトを手がけ、企業様や制作会社様のパートナーとして信頼を築いてまいりました。

【制作会社・企業様向けサポート】
  • 専任エンジニアのいない企業様に対するシステム面の不安を解消
  • 柔軟な契約形態や短納期での対応により、急なニーズにも迅速にサポート
  • システムの企画段階から運用まで、ワンストップでのサービスを提供

Webシステムの開発やサイト改善でお困りの際は、どうぞお気軽にご相談ください。小さな疑問から大規模プロジェクトまで、最適なご提案を心を込めてさせていただきます。

ぜひ、プロフィールやWeb制作会社様向け業務案内、一般企業様向け業務案内もご覧くださいね。

GitHub経験者向けBitbucket Cloud入門:Repository・Pull Request・ブランチ制限

2026.09.25

GitHubを使ったことがある開発者向けに、Bitbucket CloudのWorkspace・Project・Repositoryの関係と、cloneからPull Request、mergeまでの基本を紹介します。Branch restrictionsとMerge checksの違いや、Freeプランでの制約、HTTPS認証に使うAPI tokenについても整理します。

Bitbucket GitHub

GitHub ActionsでPHP・LaravelのCIを始める:テスト・Lint・ビルドを自動化するWorkflowの基本

2026.09.13

PHP・Laravelプロジェクトを対象に、GitHub ActionsのWorkflow、イベント、ジョブ、ステップの基本を説明します。Composerのテスト、npm ci、フロントエンドビルド、Laravel PintをCIへ組み込む方法に加え、featureブランチやPull Requestで実行される条件、失敗時のログ確認、Secrets・権限・Actionのバージョン管理についても整理します。

CI/CD GitHub Laravel PHP

Codexを使い始めた人向けGitHub入門:リポジトリ作成からPull Requestまで

2026.08.10

Windows版ChatGPTデスクトップアプリのCodexを主な例として、GitHubのアカウント・リポジトリ作成から、作業用ブランチでの変更、commit・push、Pull Request、mergeまでの流れを解説します。GitやGitHubの基本用語を丁寧に説明し、Codexの変更内容を確認してから反映するための注意点も紹介します。

Codex GitHub

ChatGPT・GitHub・Codexで設計から実装・レビューまで進める方法

2026.08.09

Codexにいきなりアプリ開発を依頼するのではなく、ChatGPTで設計と作業分解を行い、GitHub Issueへ整理してからCodexで実装する流れを紹介します。pushやPull Request、レビュー、手戻りとトークン消費を抑える考え方も説明します。

ChatGPT Codex GitHub VS Code

阿部辰也へのお仕事の依頼・お問い合わせ

軽いご相談もお気軽にどうぞ!

個人情報の取り扱いについて *必須 プライバシーポリシーをご確認いただき、同意いただける場合は「同意する」にチェックをしてください。

keyboard_double_arrow_up
TOP