応用

git submodule

別の Git リポジトリを、自分のリポジトリの特定ディレクトリに子リポジトリとして組み込みます。外部ライブラリを独立したリポジトリのまま管理したいときに使います。

構文 git submodule <subcommand> [options]

オプション

フラグ 説明
add 新しいサブモジュールを追加します(例: git submodule add <url> <path>)。
update --init サブモジュールを初期化し、記録されているコミットの内容を取得します。clone 直後によく実行します。
foreach すべてのサブモジュールに対して同じコマンドを実行します(例: git submodule foreach git pull)。
status 各サブモジュールの現在のコミットと状態を表示します。
deinit サブモジュールの作業ツリーを削除し、登録を解除します(履歴からの完全な削除には追加の手順が必要です)。

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 等)で代替できないか検討することも一般的です。