「マージしようとしたらコンフリクトが発生した…」 「どのコードを残せばいいか分からない」 「間違えてコードを消してしまいそうで怖い」
GitHubを使った共同開発で、誰もが一度は経験するコンフリクト(競合)。赤いエラーメッセージを見ると、つい焦ってしまいますよね。
でも大丈夫!コンフリクトは、複数の人が同じプロジェクトを改善しようとしている証拠。適切な手順を踏めば、必ず解決できます。
この記事では、GitHubでのコンフリクト解消について、基本的な仕組みから実践的な解決方法、そして予防策まで、すべてを分かりやすく解説します。この記事を読み終える頃には、コンフリクトを恐れず、自信を持って解決できるようになっているはずです!
コンフリクトの基本理解

そもそもコンフリクトって何?
コンフリクトを、2人で同じ文書を編集する場面に例えてみましょう。
日常での例:
田中さん:第3段落を「売上は20%増加」に変更
鈴木さん:同じ第3段落を「売上は15%増加」に変更
→ どちらが正しい?これがコンフリクト!
GitHubでも同じことが起きます。同じファイルの同じ場所を、複数の人が異なる内容に変更すると、Gitは自動的にマージできません。
なぜコンフリクトが発生するの?
主な発生パターン:
- 同じ行の編集
# developブランチ
price = 1000
# featureブランチ
price = 1200
→ マージ時にコンフリクト!
- ファイルの削除と編集
- Aさん:ファイルを削除
- Bさん:同じファイルを編集
- 大規模なリファクタリング
- 複数人が同時に構造を変更
コンフリクトの確認方法
コマンドラインでの確認
# マージを試みる
git merge feature-branch
# コンフリクトが発生した場合の表示
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
# コンフリクトしているファイルを確認
git status
# 出力例
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: index.html
both modified: style.css
GitHubのプルリクエストでの確認
プルリクエストページで、以下のような警告が表示されます:
This branch has conflicts that must be resolved
Conflicting files:
• index.html
• style.css
コンフリクトマーカーの読み方
コンフリクトマーカーの構造
コンフリクトが発生すると、ファイル内に特殊なマーカーが挿入されます。
function calculatePrice(quantity) {
<<<<<<< HEAD
const price = 1000;
const tax = 0.10;
=======
const price = 1200;
const tax = 0.08;
>>>>>>> feature-branch
return price * quantity * (1 + tax);
}
マーカーの意味:
<<<<<<< HEAD
:現在のブランチ(マージ先)の内容開始=======
:区切り線>>>>>>> feature-branch
:マージ元のブランチの内容終了
基本的なコンフリクト解消手順
ステップ1:コンフリクトの内容を理解
# 変更履歴を確認
git log --oneline --graph --all
# 各ブランチの変更内容を確認
git diff HEAD feature-branch
ステップ2:手動でコンフリクトを解消
// コンフリクト解消前
function calculatePrice(quantity) {
<<<<<<< HEAD
const price = 1000;
const tax = 0.10;
=======
const price = 1200;
const tax = 0.08;
>>>>>>> feature-branch
return price * quantity * (1 + tax);
}
// コンフリクト解消後(両方の変更を考慮)
function calculatePrice(quantity) {
const price = 1200; // feature-branchの新価格を採用
const tax = 0.10; // HEADの税率を維持
return price * quantity * (1 + tax);
}
ステップ3:解消をコミット
# 解消したファイルをステージング
git add index.html style.css
# コンフリクト解消をコミット
git commit -m "Merge feature-branch: 価格更新と税率維持"
# プッシュ
git push origin main
VSCodeでのコンフリクト解消
VSCodeの便利な機能
VSCodeは、コンフリクト解消を視覚的にサポートします。
インラインアクション:
Accept Current Change | Accept Incoming Change | Accept Both Changes | Compare Changes
使い方の手順
- コンフリクトファイルを開く
- 色付きでコンフリクト箇所が表示
- 選択肢から選ぶ
Accept Current Change
:現在のブランチの変更を採用Accept Incoming Change
:マージ元の変更を採用Accept Both Changes
:両方を残すCompare Changes
:差分を並べて表示
- 手動編集も可能
- 必要に応じて直接編集
- 保存してコミット
GitHub Web UIでの解消
プルリクエストでの解消
手順:
- プルリクエストページで「Resolve conflicts」ボタンをクリック
- Web エディタが開く
- コンフリクトマーカーを手動で編集
- 「Mark as resolved」をクリック
- 「Commit merge」でコミット
Web UIの利点:
- ローカル環境不要
- シンプルなコンフリクトに最適
- チームメンバーとリアルタイムで確認可能
複雑なコンフリクトの対処法

バイナリファイルのコンフリクト
# 画像ファイルなどのバイナリファイルの場合
git checkout --theirs path/to/image.png # 相手の変更を採用
# または
git checkout --ours path/to/image.png # 自分の変更を採用
# ステージング
git add path/to/image.png
大規模なコンフリクト
# 3-wayマージツールを使用
git mergetool
# 特定のツールを指定
git mergetool --tool=vimdiff
git mergetool --tool=meld
git mergetool --tool=kdiff3
リベース時のコンフリクト
# リベース開始
git rebase main
# コンフリクト発生時
# 1. コンフリクトを解消
# 2. ステージング
git add .
# 3. リベースを続行
git rebase --continue
# またはスキップ
git rebase --skip
# 中止したい場合
git rebase --abort
コンフリクトを防ぐベストプラクティス
1. こまめなプル/フェッチ
# 作業開始前に最新を取得
git pull origin main
# またはフェッチしてマージ
git fetch origin
git merge origin/main
2. 小さな単位でコミット
# 機能ごとに小さくコミット
git add -p # 部分的にステージング
git commit -m "feat: ユーザー認証機能を追加"
# 大きな変更を避ける
# NG: 1000行の変更を1コミット
# OK: 100行ずつ10コミット
3. ブランチ戦略の採用
# feature ブランチを短命に保つ
git checkout -b feature/add-login
# 作業(1-2日で完了)
git checkout main
git merge feature/add-login
git branch -d feature/add-login
4. .gitignoreの適切な設定
# IDEの設定ファイル
.vscode/
.idea/
*.swp
# ビルド生成物
dist/
build/
*.log
# 環境依存ファイル
.env
.env.local
チーム開発でのコンフリクト対策
コミュニケーションルール
## チーム開発ルール
1. **作業開始時の宣言**
- Slackで「index.jsを編集します」と共有
2. **プルリクエストの活用**
- 直接mainへのプッシュを禁止
- レビューを必須化
3. **定期的な同期会**
- 週1回、各自の作業内容を共有
自動化ツールの活用
# .github/workflows/auto-merge.yml
name: Auto Merge
on:
pull_request:
types: [opened, synchronize]
jobs:
auto-merge:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check conflicts
run: |
git fetch origin main
git merge-base --is-ancestor origin/main HEAD
よくあるエラーと対処法
“fatal: refusing to merge unrelated histories”
# 解決方法
git pull origin main --allow-unrelated-histories
“error: Your local changes would be overwritten”
# 一時退避してからマージ
git stash
git merge feature-branch
git stash pop
# コンフリクトがある場合は解消
“Merge conflict in deleted file”
# ファイルを削除する場合
git rm conflicted-file.txt
# ファイルを残す場合
git add conflicted-file.txt
緊急時の対処法
マージを取り消したい
# マージをなかったことに
git merge --abort
# すでにコミットした場合
git reset --hard HEAD~1
# リモートにプッシュ済みの場合(慎重に)
git revert -m 1 <merge-commit-hash>
間違えて解消した場合
# reflogで履歴を確認
git reflog
# 特定の状態に戻す
git reset --hard HEAD@{2}
実践的な例:典型的なシナリオ

シナリオ1:CSSの競合
/* main ブランチ */
.button {
background-color: blue;
padding: 10px;
}
/* feature ブランチ */
.button {
background-color: green;
padding: 15px;
border-radius: 5px;
}
/* 解消後 */
.button {
background-color: green; /* 新しい色を採用 */
padding: 15px; /* 新しいパディングを採用 */
border-radius: 5px; /* 新機能を追加 */
}
シナリオ2:関数の引数変更
// main ブランチ
function sendEmail(to, subject, body) {
// 実装
}
// feature ブランチ
function sendEmail(to, subject, body, attachments = []) {
// 実装
}
// 解消:後方互換性を保つ
function sendEmail(to, subject, body, attachments = []) {
// feature ブランチの拡張版を採用
}
よくある質問と回答
Q: コンフリクトを解消したのに、また発生する
A: 他のブランチからの変更が入っている可能性があります。git pull --rebase
で最新を取得してから作業してください。
Q: どちらの変更を選ぶべきか分からない
A: チームメンバーと相談しましょう。コードの作成者に確認するか、プルリクエストのコメントで議論してください。
Q: 大量のコンフリクトで手に負えない
A: 一度に解決せず、ファイルごとに対処しましょう。必要なら、小さなコミットに分割してマージすることも検討してください。
Q: コンフリクト解消後、テストが失敗する
A: 両方の変更を機械的にマージしただけでは、論理的な整合性が取れていない可能性があります。コードレビューとテストを徹底してください。
Q: リベースとマージ、どちらがコンフリクトが少ない?
A: 一般的にマージの方がコンフリクトは少ないですが、履歴が複雑になります。チームの方針に従ってください。
まとめ:コンフリクトと上手に付き合う
GitHubでのコンフリクトは、チーム開発では避けられないものですが、適切に対処すれば問題ありません。
重要なポイント:
- コンフリクトは悪いことではない
- 落ち着いて一つずつ解消
- ツールを活用して効率化
- コミュニケーションで予防
- 定期的な同期で最小化
解消の基本ステップ:
- コンフリクトの内容を理解
- 適切な変更を選択/編集
- テストで動作確認
- コミットして完了
この記事で学んだ技術を使えば、コンフリクトはもう怖くありません。むしろ、チームでより良いコードを作り上げる機会として捉えることができるでしょう。
さあ、自信を持ってマージボタンを押しましょう!Happy Coding! 🚀
コメント