📖 目次
- はじめに:なぜ「わざと」コンフリクトを起こすのか
- コンフリクトが起きる3つの典型パターン
- 実践!コンフリクト解消の「最強」練習3ステップ
- ステップ1:【準備編】練習用リポジトリと2人の開発者(ブランチ)を作ろう
- ステップ2:【実践編】わざとコンフリクトを起こしてみよう(同じ行を編集!)
- ステップ3:【解決編】コンフリクトを華麗に解消しよう(マーカーの読み解き方)
- チームで使える練習メニュー5選
- 現場で役立つ解消テクニック集
- よくある失敗と対処法
- まとめ:コンフリクトを制する者は、チーム開発を制す!
はじめに:なぜ「わざと」コンフリクトを起こすのか
Gitを使い始めたとき、コンフリクト(競合)って怖いですよね。
git pull や git merge をした瞬間に表示される真っ赤な CONFLICT の文字...。「何か壊しちゃうかも」「先輩に怒られるかも」という不安、すごくわかります。
でも実際の開発現場では、コンフリクトは日常茶飯事です。複数人で同じコードを触れば、必ず起きます。
だからこそ、コンフリクトは**「避けるもの」じゃなく「慣れるもの」**なんです。
安全な環境で「わざと」コンフリクトを起こし、解消するプロセスを体で覚えるのが、最速の上達法だと断言できます。
練習のメリット3つ
- 本番で焦らない → 落ち着いて「あ、コンフリですね」と対応できる。
- 解消スピードが上がる → チームの作業を止めない。
- レビューで信頼される → 「この人、ちゃんとわかってる」と評価される。
この記事のゴールは、コンフリクトを「怖いもの」から「得意なイベント」に変えること。
さあ、安全な練習場で、思いっきり「事故」って、最強の解決スキルを身につけましょう!
コンフリクトが起きる3つの典型パターン
現場でよく起きるパターンを知っておけば、解消も簡単です。
パターン1: 同じ行を別々に編集
-
シチュエーション
- Aさん: ボタンの色を赤に変更
- Bさん: 同じボタンの色を青に変更
-
コード例
<button className="bg-red-500">送信</button> <button className="bg-blue-500">送信</button> - 結果: Gitが「どっちが正しいの?」と聞いてきます。これが一番多いパターンです。
パターン2: 片方が行を削除、もう片方が編集
-
シチュエーション
- Aさん: 古い関数を削除
- Bさん: その関数にコメント追加
-
コード例
// Aさん: 関数ごと削除 // (Aさんのブランチではこのコードはもう無い) // Bさん: コメント追加 // TODO: この関数をリファクタする function oldFunction() { ... } - 結果: 削除と編集がぶつかります。「消したはずのものを編集しようとしてる」とGitが混乱します。
パターン3: 同じファイルの近い場所を編集
-
シチュエーション
- Aさん: 10行目に新機能追加
- Bさん: 15行目にバグ修正
-
結果: これはGitが賢く自動マージしてくれる(
Auto-merging)ことが多いですが、変更箇所が近すぎると「人間が意図を確認すべき」と判断し、コンフリクトすることがあります。
実践!コンフリクト解消の「最強」練習3ステップ
ここがこの記事の核心です。
理論(パターン)を学んだら、即、手を動かしましょう。
「一人二役」で2人の開発者を演じ、安全にコンフリクトを起こして解消します。
ステップ1:【準備編】練習用リポジトリと2人の開発者(ブランチ)を作ろう
まずは、誰にも迷惑がかからない、あなただけの練習場(リポジトリ)をPCに作ります。
1. 練習用フォルダを作り、Gitを起動
ターミナル(黒い画面)を開いて、以下のコマンドを打ち込みます。
# 「git-conflict-practice」という名前のフォルダを作る
mkdir git-conflict-practice
# そのフォルダに移動する
cd git-conflict-practice
# 「ここをGitで管理します!」という宣言
git init
2. 練習用のファイルと最初のセーブ(コミット)を作る
# "練習用のファイルです。" と書かれたREADME.mdファイルを作る
echo "練習用のファイルです。" > README.md
# 作ったファイルをGitの管理対象に入れる
git add .
# 「Initial commit(最初のセーブ)」というメッセージ付きでセーブ
git commit -m "Initial commit"
3. 【最重要】2人の開発者を「演じる」(ブランチ作成)
ここがキモです。あなたは今から、AさんとBさん、2人のエンジニアを演じます。
-
main(またはmaster):チームの「完成品」を置く場所。 -
feature/A:Aさんの作業用ブランチ(mainのコピー) -
feature/B:Bさんの作業用ブランチ(mainのコピー)
この2つの作業用ブランチ(コピー)を作ります。
# Aさんの作業ブランチを作る
git checkout -b feature/A
# Bさんの作業ブランチを作る(※mainから作るのがポイント)
git checkout -b feature/B main
これで準備完了です! git branch と打てば、3つのブランチが見えるはずです。
ステップ2:【実践編】わざとコンフリクトを起こしてみよう(同じ行を編集!)
ミッションは、AさんとBさんに、「README.md」の「同じ行」を「違う内容」で編集してもらうことです。(典型パターン1)
1. Aさんの作業 (feature/A ブランチで)
まずはAさんになりきります。
# Aさんの作業ブランチに切り替える
git checkout feature/A
VSCodeなどのエディタで README.md を開いて、こう書き換えましょう。
練習用のファイルです。
Aさんが書きました:リンゴ
保存したら、Aさんの作業をセーブ(コミット)します。
# 変更をGitに伝える
git add .
# Aさんの作業としてセーブ
git commit -m "A: 2行目にリンゴと書いた"
2. Aさんの作業を「完成品(main)」に合体させる
Aさん:「作業終わった!完成品に反映するぞ!」
# 完成品(main)ブランチに移動
git checkout main
# Aさんの作業(feature/A)を合体!
git merge feature/A
これは100%成功します。なぜなら、main にはまだBさんの変更が入っていないからです。
3. Bさんの作業 (feature/B ブランチで)
次にBさんになりきります。
# Bさんの作業ブランチに切り替える
git checkout feature/B
README.md を開いてみてください。
...あれ? 「リンゴ」が書かれていません!
その通りです。Bさんは「Aさんが作業する前」の main をコピーしたので、Aさんの変更をまだ知りません。これがコンフリクトの「種」です。
Bさんは、Aさんと同じ2行目に、違う内容を書きます。
練習用のファイルです。
Bさんが書きました:バナナ
保存したら、Bさんの作業をセーブ(コミット)します。
# 変更をGitに伝える
git add .
# Bさんの作業としてセーブ
git commit -m "B: 2行目にバナナと書いた"
4. 運命の時... Bさんが main にマージしようとする
Bさん:「俺の作業も終わった!完成品に合体させるぜ!」
# 完成品(main)ブランチに移動
git checkout main
# Bさんの作業(feature/B)を合体!
git merge feature/B
ドカーン!
ターミナルに、こんなメッセージが出たはずです。
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
🎉 おめでとうございます!これがコンフリクトです!
Gitが「main にはAさんの『リンゴ』が、feature/B にはBさんの『バナナ』が同じ行にある。どっちが正しいか、私には決められません!人間が決めてください!」と悲鳴を上げている状態です。
ステップ3:【解決編】コンフリクトを華麗に解消しよう(マーカーの読み解き方)
さあ、落ち着いてください。
VSCode(またはお使いのエディタ)で README.md を開いてみましょう。
衝撃的な光景が広がっているはずです。
練習用のファイルです。
<<<<<<< HEAD
Aさんが書きました:リンゴ
=======
Bさんが書きました:バナナ
>>>>>>> feature/B
これがコンフリクトマーカーです。読み解き方さえ知れば、怖くありません。
-
<<<<<<< HEAD:
ここから... -
=======:
...ここまでは、HEAD(今いるmainブランチ)の内容です。(=Aさんのリンゴ) -
>>>>>>> feature/B:
...ここまでは、マージしようとしたfeature/Bブランチの内容です。(=Bさんのバナナ)
どう解決するかは「あなた(チーム)次第」です。
選択肢1: VSCodeの便利ボタンを使う
VSCodeなら、このマーカーの上あたりに、青い文字で便利なリンクが表示されているはずです。
- Accept Current Change (HEADを採用 = Aさんの「リンゴ」を残す)
- Accept Incoming Change (feature/Bを採用 = Bさんの「バナナ」を残す)
- Accept Both Changes (両方採用 = 「リンゴ」と「バナナ」両方を残す)
選択肢2: 手動で「あるべき姿」に編集する
現場で一番多いのは、この「手動で最強の形にする」パターンです。
例えば、「AさんとBさん、両方の意見を採用しよう」と判断した場合、
これらの記号 (<<<<<<< や ======= や >>>>>>>) を全部手で消して、あなたが思う「正しい形」に書き直します。
練習用のファイルです。
Aさん:リンゴ
Bさん:バナナ
(二人ともありがとう!)
解決の儀式 (コミット)
ファイルを「あるべき姿」に修正したら、必ず保存します。
そして、ターミナルに戻って、以下のコマンドを打ち込みます。
# 1. 「私が責任を持って解決しました」とGitに報告(ステージング)
git add README.md
# 2. 解決したことをセーブ(コミット)する
# ★注意★ -m "メッセージ" は「いらない」!
git commit
git commit とだけ打つと、コミットメッセージの編集画面が開きます。
Merge branch 'feature/B' のようなメッセージが既に入っているはずです。
これは「Bブランチをマージしようとしてコンフリクトしたけど、解決したよ」という意味のコミットなので、そのまま保存して閉じてください(Vimなら :wq と打ってEnter)。
これにて、解決完了です!
main ブランチは、あなた
が判断した最終形が反映された、平和な状態に戻りました。
チームで使える練習メニュー5選
基本の練習(ステップ3)に慣れたら、他のパターンも練習してみましょう。
練習1: 基本のキ「同じ行を編集」(所要時間: 5分)
- 内容: ステップ3でやったことです。まずはこれを完璧にしましょう。
練習2: 削除vs編集パターン(所要時間: 5分)
- 内容: パターン2の練習です。
-
やり方:
-
branch-CでREADME.mdの2行目(リンゴ/バナナの行)を削除してコミット。 -
branch-DでREADME.mdの2行目を別の内容(例: "みかん")に編集してコミット。 -
mainでbranch-Cをマージし、次にbranch-Dをマージしてコンフリクトさせます。
-
練習3: CSSのコンフリクト(所要時間: 5分)
- 内容: 実際の開発で非常によくあるケースです。
-
例:
/* ブランチE: ボタンを大きく */ .button { padding: 20px; font-size: 18px; } /* ブランチF: ボタンを丸く */ .button { padding: 10px; /* ←コンフリクト! */ border-radius: 20px; } -
練習ポイント: 両方の良いところを取る(例:
padding: 20px;とborder-radius: 20px;を両方残す)という判断をしてみましょう。
練習4: JSON設定ファイルのコンフリクト(所要時間: 5分)
-
内容:
package.jsonや設定ファイルで起こると焦るパターンです。 -
例:
// ブランチG: タイムアウト変更 { "timeout": 5000, "retries": 3 } // ブランチH: リトライ回数変更 { "timeout": 3000, "retries": 5 } - 練習ポイント: JSONは構造が崩れると(カンマやカッコが変になると)即エラーになります。慎重にマージする練習です。
練習5: チーム演習「リレー解消」(所要時間: 15分)
- 内容: チーム(2人以上)でやる練習です。
-
やり方:
- 各自が別ブランチで同じファイルを編集します。
- 順番に
mainにマージしていきます。 - コンフリクトが起きたら「次の人」が解消します。
- 全員のコードが正しく入った状態でゴールです。
- 学べること: 実際のチーム開発の流れ、他の人のコードを理解する力、コミュニケーションの大切さ。
現場で役立つ解消テクニック集
テクニック1: VSCodeの3ウェイマージ(再掲)
- ステップ3で紹介した「Accept Current/Incoming/Both」ボタンです。
- 初心者はまずこれを使いこなすのが最速です。
Compare Changes(差分を詳しく見る)も便利です。
テクニック2: コンフリクトを起こさない工夫(予防)
- 小さい単位でこまめにコミット&マージする。
- 同じファイルを触るときは声かけする。(「今、〇〇のCSS触りますね!」)
-
作業前に必ず最新を取得する。
これをやっておけば、コンフリクトが起きても自分のブランチ内で解消できるので、
# 1. 自分の作業ブランチに行く git checkout feature-branch # 2. main(完成品)の最新状態を取り込む git merge main # または git rebase mainmainを汚しません。
テクニック3: rebaseでキレイな履歴を保つ
-
mergeの代わりにrebaseを使う方法です。(上級者向け) -
git rebase mainを使うと、mainの最新の変更の上に、自分の変更を「付け直す」イメージになります。 - メリット: 履歴が一直線になり、非常にキレイになります。
-
デメリット: コンフリクトが起きた場合、コミット1つずつ解消する必要があり、少し難しいです。
# コンフリクト解消したら git add . git rebase --continue # やっぱり中止したいとき git rebase --abort
テクニック4: 「わからないときはチームに聞く」
- これが一番大事なテクニックです!
- コンフリクト解消で迷ったら(「このコード、どっちが正しいかわからない...」)、すぐにチームメンバーに相談しましょう。
- 「このコード、どっちが正しいですか?」
- 「この変更の意図を教えてください」
- 「コンフリクト解消したんですが、意図が合ってるかレビューお願いします」
- 現場では、独断で相手のコードを消してしまうより、確認する方が100倍評価されます。
よくある失敗と対処法
失敗1: マーカー(<<<<<<<)を残したままコミット
-
NG例:
<<<<<<< HEADという文字列がそのままコードに残ってしまう。 -
対処法: コミット前に必ずファイル全体を確認! 慣れないうちは、コミット直前に
grep -r "<<<<<<" .などで検索するのも手です。
失敗2: 相手のコード(機能)を消しちゃった
- よくあるパターン: 自分の変更だけ残して(Accept Current)、相手が追加した新機能やバグ修正を無意識に削除してしまう。
-
対処法:
- 解消後は必ず動作確認(ローカルで動かす)
- テストを実行(
npm run testなど) - プルリクエスト(PR)でチームメンバーにレビューしてもらう。
失敗3: JSONやYAMLの構造が壊れた
- NG例: マージした結果、カンマが二重になったり、インデントが崩れたりしてアプリが起動しなくなる。
- 対処法: JSONファイルはエディタの検証機能(Linter)を使いましょう。
まとめ:コンフリクトを制する者は、チーム開発を制す!
最後に、コンフリクト解消の基本フローと、現場で評価される人の特徴をまとめます。
コンフリクト解消の基本フロー
-
落ち着いて状況確認 →
git statusでファイル確認 -
マーカーを読む → どこがぶつかっているか理解(
<<<<<<<) - 「あるべき姿」を判断 → 自分、相手、または両方?
- マーカーを全削除 → 「あるべき姿」のコードだけを残す
- 動作確認&テスト実行 → 壊れてないか確認
-
コミット →
git add→git commit
練習のコツ
- 週1回、5分だけ練習 → 習慣化が大事
- 失敗を恐れない → 練習用リポジトリなら何度でもやり直せます
現場で評価される人の特徴
- コンフリクトを恐れず、サクッと解消できる。
- わからないときは独断せず、素直にチームに聞ける。
- 解消後、ちゃんと動作確認(テスト)をする。
- (結果として)チームの作業スピードを止めない。
コンフリクトは「発生を防ぐ」より「素早く解消する」が現実的です。
最初は怖いかもしれませんが、5回も練習すれば必ず慣れます。
この記事を読んだ「今」が一番熱量があるときです。
今すぐターミナルを開いて、mkdir git-conflict-practice と打ち込んでみてください!