Gitサブモジュールのコンフリクト解消ガイド
サブモジュールのコンフリクトはなぜ起きるのか
Section titled “サブモジュールのコンフリクトはなぜ起きるのか”サブモジュールは、親リポジトリ側で「サブモジュールがどのコミット(SHA)を指すか」だけを記録しています。
そのため、複数ブランチでサブモジュールの参照先SHAが別々に更新されると、親リポジトリ上ではコンフリクトになります。
flowchart TD
A[mainでsubmodule SHA=Aを記録] --> C[マージ]
B[featureでsubmodule SHA=Bを記録] --> C
C --> D{AとBは同じSHA?}
D -- はい --> E[自動マージ]
D -- いいえ --> F[サブモジュール参照のコンフリクト]
解消の基本方針
Section titled “解消の基本方針”- まず親リポジトリ側でどのパスが衝突しているかを確認する
- サブモジュールに移動して、採用したいコミット(またはそのコミットを含むブランチ)を決める
- 親リポジトリに戻り、サブモジュールの参照先更新を1つに確定してコミットする
実際の解消手順
Section titled “実際の解消手順”1. 親リポジトリで競合ファイルを確認
Section titled “1. 親リポジトリで競合ファイルを確認”git statusboth modified: path/to/submodule のように表示されたら、サブモジュール参照の競合です。
2. サブモジュール側で採用コミットを決定
Section titled “2. サブモジュール側で採用コミットを決定”cd path/to/submodulegit log --oneline --decorate --graph -n 20必要であれば、サブモジュール内で merge や rebase を行って、最終的に採用したいコミットを作ります。
3. 親リポジトリで参照先を確定
Section titled “3. 親リポジトリで参照先を確定”cd ..git add path/to/submodulegit commit -m "Resolve submodule pointer conflict"git add path/to/submodule は、サブモジュール自体のファイル中身ではなく「どのSHAを指すか」をステージします。
よくある勘違い
Section titled “よくある勘違い”内容が同じならコンフリクトしない?
Section titled “内容が同じならコンフリクトしない?”いいえ、コンフリクトします。
内容が同じでも、コミットSHAが異なれば別コミットとして扱われるため、サブモジュール参照は競合します。
例えば次のようなケースです。
- チームA: 同じ修正をコミットしてSHAが
abc1234 - チームB: 同じ修正を別コミットとして作成してSHAが
def5678
コード差分は実質同じでも、親リポジトリから見ると abc1234 と def5678 は別参照です。
このとき、サブモジュール参照更新が同時に入ると競合します。
再発防止のコツ
Section titled “再発防止のコツ”- サブモジュール更新を含むPRは、できるだけ小さく保つ
- マージ前に親リポジトリとサブモジュールの両方で最新取り込みを行う
- 「サブモジュール更新PR」と「別機能PR」を分けてレビューしやすくする
- どのコミットを採用するかをPR説明に明記する