説明の前提
親レポジトリ:サブモジュールを取り込む方
子レポジトリ:サブモジュール側
gitlink : サブモジュールのディレクトリ(正確にはポインタ。ディレクトリの方が伝わりやすいと思う。正確性とかよりも、今回は理解のしやすさを優先)
サブモジュールをプロジェクトに初回追加したい人は、サブモジュールの初回追加 へ
初回セットアップ(git clone 直後)
# リポジトリをクローン
git clone https://github.com/you/project.git
cd project
# サブモジュールを初期化して取得(再帰的にネストも含める)
git submodule update --init --recursive
サブモジュールを「リモートの最新」に追随させる
すべてのサブモジュールを一括で更新したいとき
# 追跡対象ブランチ(多くは main/master)をフェッチしてチェックアウト
git submodule update --remote --merge # or --rebase
# (--recursive を付ければネストもまとめて)
git submodule update --remote --merge --recursive
-
--remote
….gitmodules
に記載されたbranch = <name>
の先をフェッチ -
--merge
/--rebase
… 取得した最新コミットへ移動する方法
- merge: fast-forward なら FF、衝突があればマージ- rebase: サブモジュール側でローカル開発している場合はこちら
サブモジュールを個別に更新したいとき
# 例: libs/mylib サブモジュールを開く
cd libs/mylib
git checkout main # 追跡ブランチへ
git pull --ff-only origin main
cd ../.. # 親に戻る
- サブモジュールは独立した Git リポジトリ。cd して普通に git pull しても OK。
- ブランチ未指定で git submodule update を実行すると、親リポジトリが保持している “固定コミット” に戻るので注意。
親リポジトリに「更新結果」を確定させる
- 親リポジトリのインデックスには、サブモジュールの「コミット ID」(gitlink) が記録されています。
- サブモジュール側で新しい HEAD に移動したら、その gitlink が変わります。
- 親リポジトリでコミットしてプッシュすることで、チーム全員が同じコミットを参照できます。
# 変更されたサブモジュール参照をステージ
git add path/to/submodule
# or まとめて
git add .
# コミット
git commit -m "Update submodule(s) to latest upstream"
# プッシュ
git push origin main
クローン済みの他メンバーが追従する手順
git pull # 親リポジトリを更新
git submodule update --init --recursive # 参照コミットへチェックアウト
Tips
- サブモジュール内でさらにサブモジュールを含む場合は、すべてに
--recursive
を付与 - サブモジュールの追随ブランチを変更したい場合は、
.gitmodules
にbranch = <name>
を追加 - 全 submodule で同じコマンドを実行(テストなど)したい場合は、git submodule foreach 'cmd …'
- サブモジュールをローカル開発した後、Upstream に派生 PR を出す。つまり、サブモジュール内で新ブランチ→親リポジトリでは gitlink だけ更新
troubles
症状 | 原因 | 解決 |
---|---|---|
detached HEAD と表示される |
親リポジトリが固定コミットを指しており、ブランチにいない |
git checkout <branch> でブランチへ移動 |
fatal: reference is not a tree |
親リポジトリの gitlink がリモートに存在しないコミットを指している | リモート URL 誤設定/force-push 巻き戻しの確認 |
更新後に大量の差分が出る |
.gitattributes や行末設定の不一致 |
.gitattributes をサブモジュール側にも適用し、再コミット |
サブモジュールを更新したくないのに、更新してしまった場合
サブモジュール内部でローカル変更を捨てるのがおすすめ。
cd path/to/submodule<br>git reset --hard HEAD && git clean -fd
サブモジュールの初回追加
1. サブモジュールの設定
Private repo を追加したい
git submodule add git@github.com:your-username/news.git path/to/news
Public repo を追加したい
git submodule add https://github.com:your-username/news path/to/news
2. 親レポジトリでサブモジュールの追加したことをコミット
git commit -m "プライベートリポジトリ news をサブモジュールとして追加"