症状
git submodule update を実行してもエラーが出る、または submodule の内容が更新されない。
結論:まずこれを確認
git submodule statusで submodule の状態を確認する- 初期化されていなければ
git submodule initを先に実行する --remoteオプションの有無で挙動が変わることを理解する
操作フロー
flowchart TD
A[submodule update でエラー/更新されない] --> B{git submodule status を確認}
B -->|先頭に - がある| C[初期化されていない]
B -->|先頭に + がある| D[ローカルに未コミットの変更あり]
B -->|先頭にスペース| E[正常な状態]
C --> F[git submodule init を実行]
F --> G[git submodule update を再実行]
D --> H[submodule内の変更を確認]
H --> I{変更を残す?}
I -->|Yes| J[submodule内でcommit/stash]
I -->|No| K[git submodule update --force]
E --> L{最新を取得したい?}
L -->|Yes| M[git submodule update --remote]
L -->|No| N[親リポジトリ記録のコミットを確認]
よくある原因
- submodule が初期化されていない - clone 直後は init が必要
- submodule 内にローカル変更がある - 未コミットの変更があると update が止まる
.gitmodulesと.git/configの不整合 - URL やパスが一致していない- SSH 鍵や認証の問題 - submodule のリモートにアクセスできない
- submodule のパスが変更された - 親リポジトリで移動・削除された
- ネットワークの問題 - リモートに接続できない
- サブモジュールが detached HEAD 状態 - ブランチ追跡が設定されていない
操作手順
ステップ1: submodule の状態を確認する
git submodule status
出力の見方:
| 先頭文字 | 意味 |
|---|---|
- |
初期化されていない |
+ |
親リポジトリ記録と異なるコミットをチェックアウト中 |
U |
マージコンフリクトあり |
| スペース | 正常 |
🔍 チェックポイント: 先頭が - なら初期化が必要、+ ならローカル変更を確認する
ステップ2: 初期化されていない場合
git submodule init
git submodule update
または一括で実行:
git submodule update --init
再帰的に(submodule の中の submodule も含めて)初期化する場合:
git submodule update --init --recursive
🔍 チェックポイント: 実行後に git submodule status で先頭が - でなくなっていれば成功
ステップ3: submodule 内のローカル変更を確認する
cd path/to/submodule
git status
git diff
変更を残す場合:
git stash
# または
git commit -m "ローカルの変更を保存"
変更を破棄する場合:
cd .. # 親リポジトリに戻る
git submodule update --force
🔍 チェックポイント: git status でクリーンな状態になっていれば update 可能
ステップ4: リモートの最新を取得する場合
親リポジトリに記録されたコミットではなく、submodule のリモート最新を取得する場合:
git submodule update --remote
特定の submodule のみ更新:
git submodule update --remote path/to/submodule
🔍 チェックポイント: git diff で submodule の参照コミットが変わっていれば成功
ステップ5: URL や設定の不整合を修正する
.gitmodules の設定を .git/config に同期する:
git submodule sync
git submodule update --init
🔍 チェックポイント: git config --list | grep submodule で URL が正しいことを確認
ステップ6: 認証エラーの場合
SSH 接続を確認:
ssh -T git@github.com
HTTPS に切り替える場合:
git config submodule.path/to/submodule.url https://github.com/user/repo.git
git submodule sync
🔍 チェックポイント: 認証成功のメッセージが表示されること
NG行動
| やってはいけないこと | 理由 |
|---|---|
| submodule ディレクトリを手動で rm -rf して再 clone | .git/modules 内のキャッシュと不整合が起きる |
git submodule update --force を状況確認せずに実行 |
ローカルの作業中の変更が消える |
.gitmodules を直接編集して sync を忘れる |
.git/config と不整合になり動作しない |
submodule 内で直接 git pull して親で commit しない |
他の人が clone したとき古いコミットを参照する |
よくある質問(FAQ)
Q1: --init と --remote の違いは?
A: --init は未初期化の submodule を初期化する。--remote は submodule のリモートブランチの最新コミットを取得する。親リポジトリに記録されたコミットを取得するだけなら --remote は不要。
Q2: clone 時に submodule も一緒に取得するには?
A: git clone --recurse-submodules URL を使用する。既存のリポジトリなら git submodule update --init --recursive を実行する。
Q3: submodule を完全に削除するには?
A: 以下の手順で削除する:
git submodule deinit -f path/to/submodule
rm -rf .git/modules/path/to/submodule
git rm -f path/to/submodule
git commit -m "Remove submodule"
関連するトラブル
準備中
解決しない場合
- 公式ドキュメント: Git - Submodules
- 確認すべきファイル:
.gitmodules,.git/config,.git/modules/ - 次に調べるキーワード:
git submodule foreach,git submodule absorbgitdirs,gitmodules path mismatch