【保存版】もうコンフリクトは怖くない!チーム開発でコードの衝突を極限まで減らすプロのGit運用術
「……嘘でしょ? コンフリクトが100ファイル以上……?」
チーム開発を始めたばかりの頃、誰もが一度は血の気が引くようなこの瞬間に遭遇します。自分が数日間かけて書いたコードと、同僚が更新したコードが入り乱れ、見たこともないマーカー(`<<<<<<< HEAD`)が画面いっぱいに広がる――まさに開発現場の恐怖体験ですよね。 ですが、安心してください。世界最高峰のDevOps現場においても、コンフリクトそのものをゼロにすることはできません。大切なのは「コンフリクトを発生させない運用ルール(予防)」と、「起きてしまったときに慌てず数秒で解決する技術(対処)」を身につけることです。
実は、コンフリクトはGitが「ここ、どっちのコードを残すべきか分からないから人間に判断を任せるね!」と、あなたのコードを守るために出してくれた安全装置(サイン)なのです。
この記事では、Git CLIの基礎セットアップから、チームでの運用ルール、意図的にコンフリクトを起こして解決するハンズオン、そしてプロが実践する裏ワザまで、優しく・丁寧に解説していきます。これをマスターすれば、毎日の作業が劇的に楽になり、チーム全員から信頼されるエンジニアになれますよ!
—
第1章:まずは環境構築!Gitの基礎セットアップと「Hello Conflict」体験
まずは基本となるGit CLIの環境を整えましょう。そして、あえてローカル環境で「コンフリクトを意図的に起こして解決する」という小さな実験(Hello Conflict)を行ってみます。恐怖心は「正体を知ること」で消し飛びます。
1. Gitのインストールと初期設定
お使いの環境に合わせてGitをインストールしてください。
- macOS (Homebrew): `brew install git`
- Windows: [Git for Windows official site](https://gitforwindows.org/) よりインストーラーをダウンロード
インストールが完了したら、ターミナル(Windowsの場合はGit BashまたはPowerShell)を開き、以下の「プロの推奨設定」を行っておきましょう。
1. ユーザー情報の設定(コミット履歴に記録されます)
git config –global user.name “Your Name”
git config –global user.email “your-email@example.com”
2. デフォルトブランチ名を “main” に統一
git config –global init.defaultBranch main
3. git pull 時に無駄なマージコミットを作らないよう rebase をデフォルト化(超重要!)
git config –global pull.rebase true
4. コンフリクト解消の履歴をGitに記憶させる魔法の設定(後述)
git config –global rerere.enabled true
設定の確認
git config –list
2. 精度100%の動作確認:「Hello Conflict」ハンズオン
実際に小さなリポジトリを作り、コンフリクトを発生させて解消するまでの一連の流れを体験してみましょう。
ステップA: リポジトリの作成と初期ファイル配置
練習用ディレクトリを作成して移動
mkdir git-practice
cd git-practice
Gitリポジトリの初期化
git init
初期ファイルを作成
echo “Hello, Git World!” > app.txt
コミットする
git add app.txt
git commit -m “feat: initial commit”
ステップB: ブランチを分岐させ、同じ行を別々に編集する
ここで、2つの世界(ブランチ)を作ります。
「feature/A」ブランチを作って移動
git checkout -b feature/A
app.txt の内容を書き換える
echo “Hello, Alice!” > app.txt
git commit -am “feat: change greeting for Alice”
再び main ブランチに戻る
git checkout main
別の「feature/B」ブランチを作って移動
git checkout -b feature/B
同じ app.txt の同じ行を別の内容で書き換える
echo “Hello, Bob!” > app.txt
git commit -am “feat: change greeting for Bob”
ステップC: 衝突(コンフリクト)を発生させる!
さあ、`feature/B` ブランチに `feature/A` の変更を取り込もうとしてみます。
feature/B にいる状態で feature/A をマージしてみる
git merge feature/A
すると、ターミナルに以下のようなメッセージが表示されます!
AUTO-MERGING app.txt
CONFLICT (content): Merge conflict in app.txt
Automatic merge failed; fix conflicts and then commit the result.
これがコンフリクトです!Gitが「AliceとBob、どちらの挨拶を残せばいいのか分からない!」と教えてくれました。
ステップD: コンフリクトを解決する
`app.txt` を開いてみましょう。ファイルの中身が以下のようになっているはずです。
<<<<<<< HEAD Hello, Bob! ======= Hello, Alice! >>>>>>> feature/A
- `<<<<<<< HEAD` から `=======` まで:現在のブランチ(feature/B)のコード
- `=======` から `>>>>>>> feature/A` まで:取り込もうとしたブランチ(feature/A)のコード
今回は「AliceとBob、両方に挨拶する」という解決策(手修正)を行いましょう。ファイルを以下のように直接書き換えて保存します。
Hello, Alice and Bob!
修正が終わったら、ターミナルで仕上げを行います。
修正したファイルをステージング
git add app.txt
マージコミットを完了させる
git commit -m “fix: resolve conflict between Alice and Bob greeting”
これでコンフリクトの解決完了です!`git log –oneline –graph` を叩いてみてください。綺麗に履歴が合流しているのが確認できますよ。
—
第2章:予防医学としてのGit運用ルール — 衝突を99%防ぐ5つの鉄則
コンフリクトの直し方がわかったところで、次は「そもそもコンフリクトを起こさないための日常的な運用ルール」を見ていきましょう。現場でトラブルの少ない強いチームは、例外なくこの5つの鉄則を守っています。
┌────────────────────────────────────────────────────────┐
│ コンフリクトを最小化する 5つの鉄則 │
├────────────────────────────────────────────────────────┤
│ 1. 小さく作って、小まめにコミットする (Atomic Commit) │
│ 2. 毎朝・作業前には必ず `git pull –rebase` │
│ 3. ブランチは寿命を短く(1〜2日でマージする) │
│ 4. チームで統一された「ブランチ・コミット命名規則」 │
│ 5. 大きなリファクタリング前には「声かけ」を行う │
└────────────────────────────────────────────────────────┘
鉄則1:小さく作って、小まめにコミットする (Atomic Commit)
「1週間分の作業をドカンとまとめて1回でコミット」……これはコンフリクトの最大の原因です。
変更の単位は「1つの意味を持つ最小限(アトミック)」に抑えましょう。
- ◯ バグ修正1つで1コミット
- ◯ UIデザイン調整1つで1コミット
- ✕ バグ修正と関係ないリファクタリングと新機能が混ざった巨体コミット
小まめにコミットされていれば、万が一コンフリクトしても影響範囲が小さいため、数分で解消できます。
鉄則2:頻繁に `pull`(取り込み)を行う
他のメンバーが作成したコードを、自分のローカル環境へこまめに取り込みましょう。「朝出社したとき」「昼休み明け」「新しいタスクに入る直前」など、1日に何度も最新状態に追従するのがコツです。
推奨コマンド:
main ブランチの最新状態を取得し、自分の作業履歴をその上に再構築する
git fetch origin
git rebase origin/main
※第1章の設定で `git config –global pull.rebase true` を行っていれば、作業ブランチで `git pull` を実行するだけで安全に最新化されます。
鉄則3:ブランチの寿命は「超短命」にする
ブランチが作成されてから `main` にマージされるまでの期間が長ければ長いほど、他のコードとの乖離が進み、コンフリクトの危険度が高まります。
理想的なブランチの寿命は「数時間〜長くても2日」です。巨大な機能を開発する場合は、機能を細かく分割(タスクばらし)して、少しずつメインブランチにマージしていく設計を心がけましょう。
鉄則4:命名規則をチームで統一する
ブランチ名やコミットメッセージのプレフィックス(接頭辞)を決めておくと、誰が何の作業をしているかが一目で分かり、作業範囲のバッティングを未然に防げます。
ブランチ名の推奨フォーマット
- `feature/user-login-page` (機能追加)
- `fix/checkout-button-bug` (バグ修正)
- `refactor/payment-pipeline` (コード整理)
コミットメッセージの推奨フォーマット (Conventional Commits)
[例]
feat: ユーザーログイン画面のバリデーション処理を追加
fix: 決済ボタンが二重送信される不具合を修正
docs: READMEに環境構築の手順を追記
鉄則5:影響範囲が広い変更は「コードを書く前」に相談する
関数のシグネチャ(引数や戻り値)の変更や、共通モジュールの移動、フォーマッター(PrettierやESLint等)の全ファイル適用などは、間違いなくチーム全員のブランチと衝突します。
このような「影響範囲の広い作業」を行うときは、「今から〇〇のファイルを大幅にリファクタリングしてマージします!」と Slack や Discord 等でチームに事前にチャットし、マージのタイミングを合わせるのが最高にスマートな作法です。
—
第3章:それでもコンフリクトが起きたら? プロの現場解決ワークフロー
どれだけ予防しても、開発が活発であればコンフリクトは必ず起こります。ここでは、コンフリクトが発生したときにプロが実践している「最も安全で焦らない解決手順」をご紹介します。
[コンフリクト発生]
│
▼
1. 現状確認 (git status) ──> パニックにならず「どのファイルか」特定
│
▼
2. コミュニケーション ──> 競合相手のメンバーに一声かける
│
▼
3. ツールで修正 ──> VS Code等の差分表示で正しく修正
│
▼
4. テスト&完了 ──> コードが動くか確認して commit / rebase –continue
ステップ1:現状を正確に把握する
まずは冷静になって、どのファイルが衝突しているかを確認します。
git status
ターミナルに `Unmerged paths:` と赤字で表示されるファイルが、解決すべき対象です。
ステップ2:関係者とコミュニケーションを取る
自分だけの判断で「相手の書いたコード」を消してしまうのが一番危険です。
差分を見て相手の変更意図が分からない場合は、遠慮なくそのコードを書いたメンバーに連絡しましょう。
> 会話の例:
> 「〇〇さん、お疲れ様です!今 `UserService.ts` でコンフリクトが起きていて、〇〇さんが追加した `getUserInfo` の処理と私の変更が重なっています。これ、両方の処理を残す形で合流させて大丈夫でしょうか?」
このひとことで、事故は100%防げます。
ステップ3:Visual Studio Code (VS Code) などの GUI マージツールを活用する
CLI操作にこだわりすぎる必要はありません。差分解消は VS Code などの優れたエディタを使うのが最も確実で視覚的です。
VS Codeでコンフリクトしているファイルを開くと、上部に以下のような便利なボタン(CodeLens)が表示されます。
- Accept Current Change: 自分の変更を採用
- Accept Incoming Change: 相手(取り込む側)の変更を採用
- Accept Both Changes: 両方の変更を残す
- Compare Changes: 左右に並べて差分を比較
これらをポチッとクリックするだけで、複雑なコンフリクトマーカー(`<<<<<<<` 等)を綺麗に除去・統合できます。
ステップ4:テストを実行して動作確認する
コンフリクトを解消した直後は、必ずアプリを起動するかユニットテストを実行してください。
「構文エラーは消えたけれど、ロジックとして破綻していた」というミスをここで防ぎます。
例: ユニットテストの実行
npm test
テストが通ったら、コミットして完了です!
—
💡 知っておくと救われる!プロの裏ワザコマンド
最後に、知っておくと現場で「神」と呼ばれるリベース時・マージ時のエスケープ(避難)コマンドを紹介します。
1. 「もうダメだ!一旦やり直したい!」ときの撤退コマンド
修正中にわけが分からなくなったら、マージやリベースを開始する直前の状態へ一瞬で巻き戻せます。パニックになったらまずこれを唱えましょう。
Merge 中にやり直したい場合
git merge –abort
Rebase 中にやり直したい場合
git rebase –abort
2. コンフリクト解消の履歴を自動記憶する `rerere`
第1章の設定で `git config –global rerere.enabled true` を有効にしましたね。
`rerere` とは “Reuse Recorded Resolution”(記録された解消法の再利用) の略です。
過去に一度解いたコンフリクトと同じパターンが再度発生した場合、Gitが「あ、この競合の解き方、前もやってたから自動で直しておいたよ!」と解決を自動化してくれます。長命な機能ブランチを運用する際に絶大なパワーを発揮します。
—
まとめ:コンフリクトを味方につけて、最高のチーム開発を!
チーム開発におけるGit運用の極意を振り返りましょう。
1. 基本設定: `pull.rebase true` や `rerere.enabled true` でGitを賢く育てる。
2. 予防策: 小さなコミット、短命なブランチ、頻繁な `pull`、事前コミュニケーション。
3. 発生時: `git status` で冷静に確認し、エディタのサポートを借りて関係者と相談しながら解く。
4. もしもの時: `git merge –abort` で安全に元通り。
コンフリクトは恐れるものではなく、チームのコードの品質と安全性を守るための大切なシステムです。
今回学んだルールとコマンドを胸に、明日からのGit操作を自信を持って進めてみてくださいね。毎日の開発作業が驚くほどスムーズで楽しいものに変わっていきますよ!応援しています!