Git Ready
別リポジトリを埋め込む - git submodule の使い方・オプション・サンプル

別リポジトリを埋め込む- git submodule

別の Git リポジトリをサブモジュールとして自リポジトリに取り込みます。

概念図

git submodule diagram

構文

bash
git submodule <command> [<args>]

使用例

サブモジュールを追加

bash
git submodule add https://github.com/user/lib.git libs/lib

サブモジュールごとクローン

bash
git clone --recurse-submodules <url>

クローン後にサブモジュールを初期化・取得

bash
git submodule update --init --recursive

サブモジュールを最新にする

bash
git submodule update --remote

サブモジュールとは

サブモジュールは、別のGitリポジトリを自リポジトリの特定のディレクトリに埋め込む仕組みです。

共通ライブラリやベンダー製コードを複数プロジェクトで共有したいときに使います。

親リポジトリには「サブモジュールがどのコミットを指しているか」という情報だけが記録され、ファイル本体は子リポジトリ側で管理されます。

そのため、親を git clone しただけではサブモジュールの中身は空のままで、git submodule update --init --recursive または git clone --recurse-submodules で明示的に取得する必要があります。

追加から更新までの流れ

  1. サブモジュールを追加する

    git submodule add <url> <path> で指定パスに子リポジトリを登録します。.gitmodules ファイルが自動作成され、親リポジトリに追跡されます。

  2. コミットして共有する

    .gitmodules とサブモジュールのパスを git commit して git push します。チームメンバーが取得する際は --recurse-submodules 付きでクローンします。

  3. サブモジュールを最新にする

    git submodule update --remote で子リポジトリのデフォルトブランチの最新コミットを取得します。その後、親リポジトリ側で変更をコミットして、どの子コミットを使うかを固定します。

bash
# 1. 追加
git submodule add https://github.com/user/lib.git libs/lib
git commit -m "Add lib submodule"

# 2. クローン側(初めて取得する人)
git clone --recurse-submodules <parent-url>
# すでにクローン済みなら
git submodule update --init --recursive

# 3. 最新に更新
git submodule update --remote libs/lib
git commit -am "Bump lib submodule"

ハマりポイント

  • 親リポジトリが指すのは「特定のコミット」

    サブモジュールはブランチではなく**コミットハッシュ**で固定されます。子リポジトリで新しいコミットを作っても、親側で更新をコミットし直さない限り追従しません。これを知らないと「最新にしたはずなのに反映されない」と混乱します。

  • --recurse-submodules の付け忘れ

    通常の git clonegit pull ではサブモジュールは更新されません。git config --global submodule.recurse true を設定しておくと、pull 時に自動で再帰的に更新されて便利です。

  • サブモジュールの削除は面倒

    git submodule deinit <path>git rm <path>.git/modules/<path> の手動削除、と3段階必要です。単に git rm しただけでは残骸が残ります。

  • 代替案も検討する

    サブモジュールは運用コストが高いため、モノレポ化・パッケージマネージャー(npm, pnpm workspace, Go modules 等)・git subtree などの代替も検討する価値があります。

関連コマンド