GitHubの開発フローを学ぼう!:コンフリクトが起きたときの解消手順と考え方

前回の記事では、GitHub を使ったチーム開発の中で、
コンフリクト(conflict)がなぜ起こるのか を整理しました。

今回はその続きとして、
「実際にコンフリクトが起きたとき、どう解消していけばいいか」 にフォーカスしていきます。
合わせて、「コンフリクト=悪」ではなく、調整のサインとして捉える考え方も整理してみましょう。


まずはコンフリクトの復習と心構え

前編でも触れましたが、コンフリクトは一言でいうと
「Git がどの変更を採用すべきか自動で決められない状態」です。

特にチーム開発では、

  • 同じ行を別々の人が違う内容に変更している
  • 片方で削除したコードを、もう片方ではまだ前提にして修正している

といったことが起きるため、コンフリクト自体はごく自然な現象です。

大事なのは、

  • 「自分が悪いことをしたから怒られている」わけではない
  • 「今からどのコードを正とするか、人間が決めるフェーズに入った」

と捉えることです。

これを踏まえたうえで、GitHub 上の UI から解消する方法と、ローカルで解消する方法を見ていきます。


GitHub 上の画面からコンフリクトを解消する

まずは、GitHub のブラウザ画面だけでコンフリクトを解消するパターンです。
主に テキストファイルや小さめの差分 に向いています。


GitHub 上の画面からコンフリクトを解消する

まずは、GitHub のブラウザ画面だけでコンフリクトを解消するパターンです。
主に テキストファイルや小さめの差分 に向いています。


1. プルリク画面でコンフリクトを確認する

コンフリクトがあるプルリクでは、次のような表示になります。

  • This branch has conflicts that must be resolved
  • 緑の「Merge pull request」ボタンがグレーアウトされている
  • Resolve conflicts ボタンが表示されている

この時点で、「自動ではマージできない状態」であることが分かります。


2. 「Resolve conflicts」ボタンから編集画面へ

プルリク画面の Resolve conflicts ボタンを押すと、
今回のスクリーンショットのようなコンフリクト編集画面に遷移します。

左側には「conflict_file.txt」のようにコンフリクトが発生しているファイル一覧
右側には実際のコードとコンフリクト箇所が表示されます。


3. 「Accept current / incoming / both」の違いを理解して選ぶ

コンフリクトしている部分には、画像のように
Accept current change / Accept incoming change / Accept both changes
というリンクが表示されています。

リンクの下には、

  • 上側:current change(現在のブランチ側の変更)
    例では feature/conflict-b (Current change) と書かれている行から始まるブロックです。
  • 下側:incoming change(取り込もうとしている変更)
    例では main (Incoming change) と書かれている行から始まるブロックです。

この 2つのブロックのどちらを採用するか/両方を残すかを、上の 3つのリンクで選びます。

  • current change(上側)
    <<<<<<< feature/conflict-b (Current change)
    ======= までの部分。
    この例だと、今開いているブランチ(feature/conflict-b)側の変更が current です。
  • incoming change(下側)
    =======>>>>>>> main (Incoming change) までの部分。
    この例だと、マージ先である main ブランチ側の変更が incoming です。

そのうえで、3つのリンクは次のように動きます。

  • Accept current change
    上側(current)の変更だけを残し、下側(incoming)の変更は捨てる
    =この例では feature/conflict-b の内容を採用し、main 側の変更は取り込まない。
  • Accept incoming change
    下側(incoming)の変更だけを残し、上側(current)の変更は捨てる
    =この例では main の内容を採用し、feature/conflict-b 側の変更は取り込まない。
  • Accept both changes
    current と incoming の両方の変更を、上下に並べて残した状態にする。
    文言が重複したり日本語としておかしくなることもあるので、
    ボタンを押したあとに不要な行を削るなど、少し手で整えることが多いです。

どれを選ぶか迷ったときは、
「最終的にどういう文章(コード)にしたいか」 を先に決めてから、
もっとも近いものを選んで、必要に応じて手で微調整する、という順番がおすすめです。

いずれの場合も、最終的には
<<<<<<< / ======= / >>>>>>> の行がすべて消えていることを確認してから、
画面下部の 「Mark as resolved」→「Commit merge」 で確定します。


4. GitHub 上でのコンフリクト解消が向いているケース・向いていないケース

GitHub 上での解消は便利ですが、得意・不得意があります。

  • 向いているケース
    ・テキスト差分が少ないとき
    ・仕様としてどちらを優先するかが明確なとき
    ・README やドキュメント、ちょっとした文言修正 など
  • 向いていないケース
    ・差分が大きい or ファイル数が多いとき
    ・動作確認が必須なコード(アプリのロジックなど)
    ・手元でテストを回しながら調整したいとき

後者の場合は、次に紹介するローカルでの解消がおすすめです。


ローカルでコンフリクトを解消する基本パターン

次に、ローカル環境でコンフリクトを解消するパターンです。
一見難しそうに見えますが、流れ自体はいつもどおりの Git 操作に少しだけステップが増えるだけです。


1. 最新の main を取得する

まずは main ブランチを最新の状態にしておきます。


2. 作業ブランチに main を取り込む

この git merge main のタイミングで、ローカルでもコンフリクトが発生します。
ターミナルには Automatic merge failed; fix conflicts and then commit the result. といったメッセージが表示されます。


3. エディタでコンフリクト箇所を修正する

ここからの流れは、GitHub 上で解消する場合とほぼ同じです。
コンフリクトしているファイルをエディタで開くと、次のようなマーカーが入っています。

VS Code などのエディタを使っている場合は、「現在の変更を取り込む」「入力側の変更を取り込む「両方の変更を取り込む」「変更の比較」といったボタンが表示されるます。

いずれにせよ、
最終的にどういうコードが正しいかを考えて編集し、コンフリクトマーカーをすべて削除するのがゴールです。


4. 修正後に add・commit する

コンフリクト箇所をすべて修正し終えたら、通常どおり git addgit commit を行います。

このコミットは、「コンフリクト解消だけ」を行ったコミットになります。
あとから履歴を追ったときにも、どこでコンフリクトを解消したか分かりやすくなるのでおすすめです。


5. リモートに push してプルリクを更新する

最後に、いつもどおりリモートに push します。

これで GitHub 上のプルリクにも、コンフリクト解消済みの状態が反映されます。
プルリク画面を確認して、「This branch has conflicts…」の表示が消えていること
「Merge pull request」ボタンが押せる状態になっていることを確認しましょう。


コンフリクトは「悪」ではなく調整のサイン

最後に、コンフリクトとの付き合い方について少しだけ整理しておきます。


コンフリクトが出る=チーム開発が回っている証拠でもある

コンフリクトがまったく発生しないプロジェクトは、

  • 1人だけが開発している
  • みんなが main に直接コミットしている
  • そもそも変更があまり行われていない

といったパターンであることも多いです。

複数人が、同じコードベースを日々改善していけば、コンフリクトはある程度必ず発生します
大事なのは、
「あ、ここはみんなが触りやすい場所なんだな」 というサインとして受け取り、
設計や責務分割を見直すきっかけにすることです。


「誰が悪いか」ではなく、「どうすれば次はスムーズか」を見る

コンフリクトが起きると、つい
「どっちが先に直してたか」「どっちのミスか」 という話になりがちです。
ですが、実務的には、次のように考えた方が建設的です。

  • このファイル、1つに責務を詰め込みすぎてないか?
  • ブランチの粒度が大きすぎないか?
  • 事前に共有しておけば、同じ場所を同時に触らずに済んだのでは?

この記事で挙げたチェックリストのような簡単なルールをチーム内で共有しておくだけでも、
コンフリクトの頻度や「ダメージ」をかなり抑えることができます。


まとめ:怖がらずに付き合っていこう

今回の記事では、GitHub のコンフリクトについて、

  • コンフリクトは、Git が自動では決めきれない状態になったサインであること
  • GitHub 上の Resolve conflicts 画面から、その場で直せるケースがあること
  • ローカルでは、「main を取り込む → エディタで修正 → add / commit」という流れで解消できること
  • コンフリクトはゼロにするものではなく、起きる場所とタイミングをコントロールする対象であること

といったポイントを中心にまとめました。

コンフリクトは、最初はどうしても怖く感じるものですが、
一度手順を体験してしまえば、「ああ、またいつものやつね」 くらいの存在になっていきます。

この記事をきっかけに、ぜひ自分のプロジェクトでも
「コンフリクトが出たらどう動くか」 を一度シミュレーションしてみてください。
そのうえで、チーム内での簡単なルールづくりにもつなげてもらえればうれしいです。

 
 

ブログランキングに参加しています。クリックして応援していただけると嬉しいです。


人気ブログランキング
ブログランキング・にほんブログ村へ
にほんブログ村