日本語 ▾ トピック ▾ 最新バージョン ▾ gitsubmodules は 2.44.0 で最終更新

名前

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

概要

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

説明

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

ファイルシステム上では、サブモジュールは通常(常にではありません - 以下のFORMSを参照)、(i) スーパープロジェクトの`$GIT_DIR/modules/`ディレクトリの下にあるGitディレクトリ、(ii) スーパープロジェクトのワーキングディレクトリ内にあるワーキングディレクトリ、そして(i)を指すサブモジュールのワーキングディレクトリのルートにある`.git`ファイルで構成されます。

サブモジュールが`$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のポーセリンレイヤーに追加のヒントを与えます。例えば、`submodule.foo.url`設定はサブモジュールをどこから取得するかを指定します。

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

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

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

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

    • 転送サイズ:現在の形式では、Gitはワーキングツリー全体が存在することを要求します。フェッチまたはクローン時に部分的なツリーを転送することはできません。作業中のプロジェクトがスーパープロジェクト内でサブモジュールとして結合された複数のリポジトリで構成されている場合、関心のないリポジトリのワーキングツリーをフェッチすることを避けることができます。

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

サブモジュールの設定

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

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

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

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

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

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

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

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

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

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

形式

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

  • DESCRIPTIONで説明されている基本的な形式で、Gitディレクトリ、ワーキングディレクトリ、`gitlink`、および`.gitmodules`エントリを持つもの。

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

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

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

  • 初期化解除されたサブモジュール:`gitlink`と`.gitmodules`エントリは存在するが、サブモジュールのワーキングディレクトリがないもの。サブモジュールのGitディレクトリは、初期化解除後も残されているため存在する可能性があります。代わりに、ワーキングディレクトリとなるはずのディレクトリは空です。

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

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

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

    サブモジュールを完全に削除するには、`$GIT_DIR/modules//`を手動で削除してください。

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

サブモジュールは以下の場合にアクティブとみなされます。

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

    または

  2. ・サブモジュールのパスが`submodule.active`のパススペックに一致する場合

    または

  3. ・`submodule..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..active`が`false`に設定されている場合、またはサブモジュールのパスが`submodule.active`のパススペックで除外されている場合、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*はそれ自身のactiveフラグによるもので、他のすべてはサブモジュールのアクティブパススペックによるものです。これにより、`.url`フィールドの有無にかかわらず、*baz*を除く*b*で始まる任意のサブモジュールもアクティブであると指定されます。

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

# 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 submodule`の`init`および`update`サブコマンドは、サブモジュールがワーキングツリー内で適切なリビジョンでチェックアウトされた状態を維持します。あるいは、`submodule.recurse`を設定することで、`checkout`がサブモジュールに再帰するようにすることもできます(`submodule.recurse`は他のGitコマンドにも影響することに注意してください。完全なリストについてはgit-config[1]を参照してください)。

GIT

git[1]スイートの一部

scroll-to-top