Skip to content

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[サブモジュール参照のコンフリクト]
  1. まず親リポジトリ側でどのパスが衝突しているかを確認する
  2. サブモジュールに移動して、採用したいコミット(またはそのコミットを含むブランチ)を決める
  3. 親リポジトリに戻り、サブモジュールの参照先更新を1つに確定してコミットする

1. 親リポジトリで競合ファイルを確認

Section titled “1. 親リポジトリで競合ファイルを確認”
Terminal window
git status

both modified: path/to/submodule のように表示されたら、サブモジュール参照の競合です。

2. サブモジュール側で採用コミットを決定

Section titled “2. サブモジュール側で採用コミットを決定”
Terminal window
cd path/to/submodule
git log --oneline --decorate --graph -n 20

必要であれば、サブモジュール内で mergerebase を行って、最終的に採用したいコミットを作ります。

3. 親リポジトリで参照先を確定

Section titled “3. 親リポジトリで参照先を確定”
Terminal window
cd ..
git add path/to/submodule
git commit -m "Resolve submodule pointer conflict"

git add path/to/submodule は、サブモジュール自体のファイル中身ではなく「どのSHAを指すか」をステージします。

内容が同じならコンフリクトしない?

Section titled “内容が同じならコンフリクトしない?”

いいえ、コンフリクトします。
内容が同じでも、コミットSHAが異なれば別コミットとして扱われるため、サブモジュール参照は競合します。

例えば次のようなケースです。

  • チームA: 同じ修正をコミットしてSHAが abc1234
  • チームB: 同じ修正を別コミットとして作成してSHAが def5678

コード差分は実質同じでも、親リポジトリから見ると abc1234def5678 は別参照です。
このとき、サブモジュール参照更新が同時に入ると競合します。

  • サブモジュール更新を含むPRは、できるだけ小さく保つ
  • マージ前に親リポジトリとサブモジュールの両方で最新取り込みを行う
  • 「サブモジュール更新PR」と「別機能PR」を分けてレビューしやすくする
  • どのコミットを採用するかをPR説明に明記する