Git submodule のファイルが空のまま更新できない
submodule は clone 時に自動取得されない。
--recurse-submodules 付きで clone するか、後から git submodule update --init --recursive を実行する。
親リポジトリと submodule は別の HEAD を持つため pull とのセット運用も必要。
公開:
要約
Git submodule のディレクトリは clone しただけでは中身が空のまま。git clone --recurse-submodules を付けるか、後から git submodule update --init --recursive を実行することで取得できる。
親リポジトリと submodule は別の HEAD を持つので、親を pull した後の同期も忘れやすい。
よくある原因
- clone 時にオプション未指定:
git clone <url>だけ実行すると.gitmodulesに書かれた submodule の中身は取得されず、ディレクトリだけが空の状態で作られる。 - submodule 初期化忘れ: 後から submodule が追加されたリポジトリで
git pullしても、submodule ディレクトリは空のままでgit submodule update --initが必要。 - 親リポジトリの更新後: 親が submodule の新しいコミットを指していても、ローカルの submodule HEAD は古いコミットのままになり、
git submodule updateで追従させる必要がある。 - URL 変更未反映:
.gitmodulesで submodule の URL が変わったが、ローカルの.git/config側は古い URL を保持しているため fetch 先が間違っている。
解決策
1. 初回 clone でまとめて取得
git clone --recurse-submodules https://example.com/parent.git--recurse-submodules を付けると、親 clone 完了後に自動で submodule init + submodule update が走る。
2. 既存 clone を初期化する
git submodule update --init --recursive--init は .gitmodules を読み .git/config に submodule を登録するステップ、--recursive はネストした submodule にも適用する。
詳しくは git-submodule 公式ドキュメント を参照。
3. 親の pull とセットで実行
git pull
git submodule update --init --recursive親の commit が submodule の新しい SHA を指していると、git status で modified content と表示されることがある。update で submodule の HEAD を親が指す SHA に揃える。
4. URL が変わったとき
git submodule sync --recursive
git submodule update --init --recursive.gitmodules の url 行を .git/config 側に反映するのが sync。
リポジトリ移行後にはこの 2 行を流すと安全。
さらに踏み込んだ運用は Pro Git の Submodules 章 が詳しい。