Git
英語 ▾ トピック ▾ 最新バージョン ▾ gitsubmodulesは2.44.0で最後に更新されました

名前

gitsubmodules - あるリポジトリを別のリポジトリ内にマウントする

概要

.gitmodules, $GIT_DIR/config
git submodule
git <command> --recurse-submodules

説明

サブモジュールとは、別のリポジトリ内に埋め込まれたリポジトリです。 サブモジュールは独自の履歴を持ち、埋め込まれているリポジトリはスーパープロジェクトと呼ばれます。

ファイルシステム上では、サブモジュールは通常(ただし常にではありません - 下記の「形式」を参照)、(i)スーパープロジェクトの `$GIT_DIR/modules/` ディレクトリ以下にある Git ディレクトリ、(ii)スーパープロジェクトの作業ディレクトリ内にある作業ディレクトリ、およびサブモジュールの作業ディレクトリのルートにある ` .git` ファイル((i)を指す)で構成されます。

サブモジュールが `$GIT_DIR/modules/foo/` に Git ディレクトリを持ち、`path/to/bar/` に作業ディレクトリを持っていると仮定すると、スーパープロジェクトは `path/to/bar` のツリー内の `gitlink` エントリと、` .gitmodules` ファイル(gitmodules[5] を参照)内の `submodule.foo.path = path/to/bar` 形式のエントリを介してサブモジュールを追跡します。

`gitlink` エントリには、スーパープロジェクトがサブモジュールの作業ディレクトリが存在することを期待するコミットのオブジェクト名が含まれています。

`.gitmodules` ファイルの `submodule.foo.*` セクションは、Git の porcelain 層に追加のヒントを提供します。 たとえば、`submodule.foo.url` 設定は、サブモジュールを取得する場所を指定します。

サブモジュールは、少なくとも 2 つの異なるユースケースで使用できます。

  1. 独立した履歴を維持しながら別のプロジェクトを使用する。 サブモジュールを使用すると、両方のプロジェクトの履歴を個別に保持しながら、別のプロジェクトの作業ツリーを独自の作業ツリー内に含めることができます。 また、サブモジュールは任意のバージョンに固定されているため、他のプロジェクトはスーパープロジェクトに影響を与えることなく独立して開発できます。これにより、スーパープロジェクトは必要な場合にのみ新しいバージョンに修正できます。

  2. (論理的に単一の)プロジェクトを複数のリポジトリに分割し、それらを結び付ける。 これは、よりきめ細かいアクセスを実現するための Git の実装の現在の制限を克服するために使用できます。

    • Git リポジトリのサイズ:現在の形式では、Git は、ツリー間のデルタ計算によって圧縮されないコンテンツを含む大きなリポジトリではうまくスケールアップしません。 たとえば、サブモジュールを使用して大きなバイナリ資産を保持し、これらのリポジトリを浅くクローンすることができます。そのため、ローカルに大きな履歴を持つ必要はありません。

    • 転送サイズ:現在の形式では、Git は作業ツリー全体が存在する必要があります。 fetch や clone で部分的なツリーを転送することはできません。 作業しているプロジェクトがスーパープロジェクトのサブモジュールとして結び付けられた複数のリポジトリで構成されている場合、関心のないリポジトリの作業ツリーのフェッチを回避できます。

    • アクセス制御:ユーザーのサブモジュールへのアクセスを制限することにより、異なるユーザーに対して読み取り/書き込みポリシーを実装するために使用できます。

サブモジュールの設定

サブモジュールの操作は、次のメカニズムを使用して設定できます(優先順位の高い順)

  • パス指定の一部としてサブモジュールを受け入れることをサポートするコマンドのコマンドライン。 ほとんどのコマンドには、サブモジュールに再귀するかどうを指定するブール値フラグ `--recurse-submodules` があります。 例としては、`grep` と `checkout` があります。 一部のコマンドは、`fetch` や `push` など、サブモジュールがどのように影響を受けるかを指定できる列挙型を取ります。

  • サブモジュール内の設定。 これには、サブモジュール内の `$GIT_DIR/config` が含まれますが、サブモジュール内でのコマンドの動作を指定する `.gitattributes` や `.gitignore` ファイルなどのツリーの設定も含まれます。

    たとえば、スーパープロジェクトで `git status --ignore-submodules=none` を実行すると、サブモジュールの `.gitignore` ファイルからの影響が観察されます。 これは、サブモジュールで `status` を実行することにより、サブモジュールの作業ディレクトリから情報を収集しますが、サブモジュールの `.gitignore` ファイルに注意を払います。

    サブモジュールの `$GIT_DIR/config` ファイルは、スーパープロジェクトで `git push --recurse-submodules=check` を実行するときに役立ちます。これは、サブモジュールにリモートに公開されていない変更があるかどうかを確認するためです。 リモートは、通常どおり `$GIT_DIR/config` ファイルのサブモジュールで設定されます。

  • スーパープロジェクトの設定ファイル `$GIT_DIR/config`。 Git はアクティブなサブモジュールにのみ再帰します(以下の「アクティブなサブモジュール」セクションを参照)。

    サブモジュールがまだ初期化されていない場合、サブモジュール内の設定はまだ存在しないため、たとえば、サブモジュールを取得する場所をここで設定します。

  • スーパープロジェクト内の `.gitmodules` ファイル。 プロジェクトは通常、このファイルを使用して、サブモジュールの名前とそのパスに必要なマッピングのための上流リポジトリコレクションのデフォルトを提案します。

    このファイルは主に、スーパープロジェクト内のサブモジュールの名前とパスの間のマッピングとして機能するため、サブモジュールの Git ディレクトリを見つけることができます。

    サブモジュールが初期化されたことがない場合、これはサブモジュール設定が見つかる唯一の場所です。 サブモジュールを取得する場所を指定するための最後のフォールバックとして機能します。

形式

サブモジュールは次の形式をとることができます。

  • 説明で説明されている基本的な形式。Git ディレクトリ、作業ディレクトリ、`gitlink`、および `.gitmodules` エントリがあります。

  • 「古い形式」のサブモジュール:埋め込まれた `.git` ディレクトリを持つ作業ディレクトリ、およびスーパープロジェクト内の追跡 `gitlink` および `.gitmodules` エントリ。 これは通常、古いバージョンの Git を使用して生成されたリポジトリにあります。

    これらの古い形式のリポジトリを手動で構築することは可能です。

    初期化解除または削除された場合(下記参照)、サブモジュールの Git ディレクトリは自動的にスーパープロジェクトの `$GIT_DIR/modules/<name>/` に移動されます。

  • 初期化解除されたサブモジュール:`gitlink` と `.gitmodules` エントリはありますが、サブモジュールの作業ディレクトリはありません。 サブモジュールの Git ディレクトリは、初期化解除後に Git ディレクトリが保持されるため、存在する可能性があります。 作業ディレクトリであるはずのディレクトリは代わりに空です。

    サブモジュールは、`git submodule deinit` を実行することで初期化解除できます。 作業ディレクトリを空にすることに加えて、このコマンドはスーパープロジェクトの `$GIT_DIR/config` ファイルのみを変更するため、スーパープロジェクトの履歴は影響を受けません。 これは `git submodule init` を使用して元に戻すことができます。

  • 削除されたサブモジュール:サブモジュールは、`git rm <submodule-path> && git commit` を実行することで削除できます。 これは `git revert` を使用して元に戻すことができます。

    削除により、スーパープロジェクトの追跡データ(`gitlink` エントリと `.gitmodules` ファイルのセクションの両方)が削除されます。 サブモジュールの作業ディレクトリはファイルシステムから削除されますが、Git ディレクトリは、別のリポジトリからフェッチすることなく過去のコミットをチェックアウトできるようにするために保持されます。

    サブモジュールを完全に削除するには、手動で `$GIT_DIR/modules/<name>/` を削除します。

アクティブなサブモジュール

サブモジュールは、次の場合にアクティブと見なされます。

  1. `submodule.<name>.active` が `true` に設定されている場合

    または

  2. サブモジュールのパスが `submodule.active` のパス指定と一致する場合

    または

  3. `submodule.<name>.url` が設定されている場合

これらは、この順序で評価されます。

例えば

[submodule "foo"]
  active = false
  url = https://example.org/foo
[submodule "bar"]
  active = true
  url = https://example.org/bar
[submodule "baz"]
  url = https://example.org/baz

上記の設定では、サブモジュール *bar* と *baz* のみがアクティブです。*bar* は(1)が原因で、*baz* は(3)が原因です。 *foo* は(1)が(3)よりも優先されるため、非アクティブです。

(3) は歴史的な遺物であり、(1) と (2) でサブモジュールがアクティブでないことが指定されている場合は無視されます。言い換えれば、submodule.<name>.activefalse に設定されている場合、または submodule.active の pathspec でサブモジュールのパスが除外されている場合、URL の有無は関係ありません。これは、以下の例で示されています。

[submodule "foo"]
  active = true
  url = https://example.org/foo
[submodule "bar"]
  url = https://example.org/bar
[submodule "baz"]
  url = https://example.org/baz
[submodule "bob"]
  ignore = true
[submodule]
  active = b*
  active = :(exclude) baz

ここでは、 *baz* (foo、bar、bob) を除くすべてのサブモジュールがアクティブです。 *foo* は自身のアクティブフラグにより、その他は *b* で始まり *baz* を除くすべてのサブモジュールもアクティブであることを指定する submodule active pathspec によりアクティブです。.url フィールドの有無は関係ありません。

サードパーティライブラリのワークフロー

# Add a submodule
git submodule add <URL> <path>
# Occasionally update the submodule to a new version:
git -C <path> checkout <new-version>
git add <path>
git commit -m "update submodule to new version"
# See the list of submodules in a superproject
git submodule status
# See FORMS on removing submodules

人為的に分割されたリポジトリのワークフロー

# Enable recursion for relevant commands, such that
# regular commands recurse into submodules by default
git config --global submodule.recurse true
# Unlike most other commands below, clone still needs
# its own recurse flag:
git clone --recurse <URL> <directory>
cd <directory>
# Get to know the code:
git grep foo
git ls-files --recurse-submodules
注記
git ls-files も独自の --recurse-submodules フラグが必要です。
# Get new code
git fetch
git pull --rebase
# Change worktree
git checkout
git reset

実装の詳細

サブモジュールを含むリポジトリをクローンまたはプルする場合、デフォルトではサブモジュールはチェックアウトされません。clone にサブモジュールを再帰的に処理するように指示できます。 git submoduleinit および update サブコマンドは、サブモジュールをチェックアウトした状態にし、作業ツリー内の適切なリビジョンに維持します。 あるいは、submodule.recurse を設定して、checkout がサブモジュールを再帰的に処理するようにすることもできます (submodule.recurse は他の Git コマンドにも影響することに注意してください。完全なリストについては、git-config[1] を参照してください)。

関連項目

GIT

git[1] スイートの一部

scroll-to-top