マージコンフリクトとは?
マージコンフリクト(merge conflict)は、Gitが自動的に変更を統合できない状況です。同じファイルの同じ部分を複数の人が異なる方法で変更した場合に発生します。
よくある困りごと
😱 コンフリクトへの恐怖
- 「コンフリクトが怖くてマージできない」
- 「解決方法が分からず作業が止まる」
- 「間違って重要なコードを消してしまいそう」
🔥 解決の失敗
- 「適当に解決したらバグが発生」
- 「他の人の変更を誤って削除」
- 「コンフリクトマーカーを残したままコミット」
コンフリクトが発生する状況
1. 同じ行の編集
# Aさんの変更
const greeting = "Hello, World!";
# Bさんの変更
const greeting = "こんにちは、世界!";
2. 一方が削除、もう一方が編集
# Aさん: ファイルを削除
# Bさん: 同じファイルを編集
3. ファイル名の変更
# Aさん: user.js → users.js
# Bさん: user.js → person.js
コンフリクトの解決手順
1. コンフリクトの発生
# マージを試みる
git merge feature/branch
# コンフリクトが発生
# Auto-merging src/app.js
# CONFLICT (content): Merge conflict in src/app.js
# Automatic merge failed; fix conflicts and then commit the result.
2. コンフリクトの確認
# コンフリクトしているファイルを確認
git status
# On branch main
# You have unmerged paths.
# (fix conflicts and run "git commit")
#
# Unmerged paths:
# (use "git add <file>..." to mark resolution)
# both modified: src/app.js
3. コンフリクトマーカーの理解
<<<<<<< HEAD
const message = "Hello from main branch";
=======
const message = "Hello from feature branch";
>>>>>>> feature/branch
<<<<<<< HEAD
: 現在のブランチ(HEAD)の内容開始=======
: 区切り線>>>>>>> feature/branch
: マージしようとしているブランチの内容終了
4. 手動での解決
// コンフリクトを解決(例:両方の変更を採用)
const message = "Hello from main branch";
const featureMessage = "Hello from feature branch";
5. 解決の完了
# 解決したファイルをステージング
git add src/app.js
# マージを完了
git commit
高度なコンフリクト解決
3-wayマージの理解
Gitは3つのバージョンを比較してマージします:
- 共通の祖先(base)
- 現在のブランチ(ours)
- マージするブランチ(theirs)
# 3-wayマージの情報を表示
git checkout --conflict=diff3 src/app.js
結果:
<<<<<<< HEAD
const message = "Hello from main branch";
||||||| merged common ancestors
const message = "Hello, World!";
=======
const message = "Hello from feature branch";
>>>>>>> feature/branch
マージツールの使用
# マージツールを設定
git config --global merge.tool vimdiff
# マージツールを起動
git mergetool
戦略的な解決方法
1. 自分の変更を優先(ours)
# 特定のファイルで自分の変更を採用
git checkout --ours src/app.js
git add src/app.js
2. 相手の変更を優先(theirs)
# 特定のファイルで相手の変更を採用
git checkout --theirs src/app.js
git add src/app.js
3. マージを中止
# マージを中止して元の状態に戻る
git merge --abort
コンフリクトの予防策
1. こまめなマージ/リベース
# 定期的にmainブランチの変更を取り込む
git checkout feature/branch
git pull origin main
git merge main # またはgit rebase main
2. 小さなPull Request
- 変更範囲を限定
- レビューとマージを迅速に
- コンフリクトの可能性を減らす
3. コミュニケーション
- 作業前にチームに共有
- 同じファイルを編集する場合は調整
- ペアプログラミングの活用
4. ファイル構造の工夫
// 悪い例:全てを1つのファイルに
// app.js (5000行)
// 良い例:機能ごとに分割
// auth/login.js
// auth/logout.js
// user/profile.js
// user/settings.js
よくあるコンフリクトパターンと対処法
package.jsonのコンフリクト
# package-lock.jsonでコンフリクトした場合
rm package-lock.json
npm install
git add package-lock.json
自動生成ファイルのコンフリクト
# ビルド成果物は.gitignoreに追加
echo "dist/" >> .gitignore
echo "build/" >> .gitignore
実践演習
CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$
█
ファイルツリー
/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log
CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$
█
ファイルツリー
/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log
まとめ
マージコンフリクトは避けられないものですが、適切な知識とツールがあれば恐れる必要はありません。コンフリクトは、チームメンバー間のコミュニケーションを促進し、コードの品質を向上させる機会でもあります。
次のレッスンでは、履歴をきれいに保つための「リベース」について学びます。