git submodule
別の Git リポジトリを、自分のリポジトリの特定ディレクトリに子リポジトリとして組み込みます。外部ライブラリを独立したリポジトリのまま管理したいときに使います。
構文
git submodule <subcommand> [options] git submodule は、あるリポジトリの中に、別の独立した Git リポジトリを子リポジトリとして組み込む仕組みです。共通ライブラリやテーマなど、複数プロジェクトで再利用したいコードを別リポジトリとして管理しつつ、必要なプロジェクトに取り込みたいときに使います。
サブモジュールを追加する
# 外部リポジトリを libs/awesome-lib として組み込む
git submodule add https://github.com/example/awesome-lib.git libs/awesome-lib
実行すると、.gitmodules というファイルが自動生成されます。
[submodule "libs/awesome-lib"]
path = libs/awesome-lib
url = https://github.com/example/awesome-lib.git
親リポジトリには、サブモジュールの実体ファイルではなく「どのコミットを参照しているか」という情報だけが記録されます。
git add .gitmodules libs/awesome-lib
git commit -m "awesome-lib をサブモジュールとして追加"
サブモジュールを含むリポジトリを clone する
サブモジュールを含むリポジトリを通常通り clone しても、サブモジュールのディレクトリは空のままです。
# 通常の clone(サブモジュールの中身は空)
git clone https://github.com/example/main-project.git
# サブモジュールも含めて取得する
cd main-project
git submodule update --init --recursive
または、最初から一括で取得することもできます。
git clone --recurse-submodules https://github.com/example/main-project.git
サブモジュールの状態を確認する
git submodule status
a1b2c3d4e5f6789 libs/awesome-lib (v2.1.0)
+f9e8d7c6b5a4321 libs/other-lib (heads/main)
先頭が + の場合、そのサブモジュールは親リポジトリに記録されているコミットと異なる状態(ローカルで更新した等)であることを示します。
サブモジュールを最新化する
# 個別のサブモジュールに入って更新
cd libs/awesome-lib
git pull origin main
cd ../..
git add libs/awesome-lib
git commit -m "awesome-lib を最新化"
# すべてのサブモジュールに同じコマンドを一括実行
git submodule foreach git pull origin main
サブモジュールを削除する
# サブモジュールの作業ツリーを削除し登録を解除
git submodule deinit -f libs/awesome-lib
# .git/modules 以下のキャッシュとディレクトリ自体も削除
git rm -f libs/awesome-lib
rm -rf .git/modules/libs/awesome-lib
ヒント
- サブモジュールは「特定のコミット」を固定的に参照する仕組みです。サブモジュール側で新しいコミットがあっても、親リポジトリ側で明示的に更新してコミットしない限り反映されません。
- 運用が複雑になりがちなため、モノレポ構成やパッケージマネージャ(npm workspaces 等)で代替できないか検討することも一般的です。