SYNOPSIS

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

DESCRIPTION

サブモジュール(submodule)は、別のリポジトリ内に埋め込まれたリポジトリです。サブモジュールにはサブモジュール独自の履歴があります。 それが埋め込まれているリポジトリはスーパープロジェクト(superproject)と呼ばれます。

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

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

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

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

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

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

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

    Gitリポジトリのサイズ

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

    転送サイズ

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

    アクセス制御

    サブモジュールへのユーザーアクセスを制限することにより、 さまざまなユーザーの読み取り/書き込みポリシーを実装できます。

The configuration of submodules

サブモジュール操作は、以下のメカニズムを使用して構成(configure)できます(優先順位の高い順です):

  • パススペックの一部としてサブモジュールを使用することをサポートするコマンドのコマンドライン。 ほとんどのコマンドには、サブモジュールに再帰するかどうかを指定するブールフラグ --recurse-submodules があります。 例としては、 grepcheckout があります。 fetchpush などの一部のコマンドは、サブモジュールがどのように影響を受けるかを指定できる列挙型を取ります。

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

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

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

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

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

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

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

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

FORMS

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

DESCRIPTIONで説明されている、Gitディレクトリと、作業ディレクトリと、 gitlink と、 `.gitmodules`エントリ、を含む基本形式。

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

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

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

非初期化された(deinitialized)サブモジュール: gitlink.gitmodules エントリがありますが、サブモジュールの作業ディレクトリはありません。サブモジュールのGitディレクトリは、Gitディレクトリを初期化解除した後も保持されているため、そこにある可能性があります。 代わりに、作業ディレクトリであるはずのディレクトリが空になります。

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

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

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

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

ACTIVE SUBMODULES

サブモジュールがアクティブと見なされるには、

  1. if submodule.<name>.activetrue に設定されている

    or

  2. if サブモジュールのパスが submodule.active のパススペックと一致する

    or

  3. if 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

上記の構成では、サブモジュール barbaz のみがアクティブになります。 bar は上記(1)により、 baz は上記(3)によりアクティブになります。 (1)が(3)よりも優先されるため、 foo は非アクティブです。

上記(1)と(2)でサブモジュールがアクティブでないことを指定している場合は、(3)は歴史的遺物であり、無視されることに注意してください。 つまり、 submodule.<name>.activefalse に設定されている場合、またはサブモジュールのパスが 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 はそれ自体のアクティブフラグによるものであり、他のすべては submodule active パススペック によるものです。これは、 .url フィールドの存在に関係なく、baz を除く b で始まるすべてのサブモジュールもアクティブであることを指定します。

Workflow for a third party library

  # サブモジュールの追加
  git submodule add <URL> <path>

  # ときどきサブモジュールを新しいバージョンに更新します:
  git -C <path> checkout <new version>
  git add <path>
  git commit -m "update submodule to new version"

  # スーパープロジェクト内でサブモジュールのリストを表示します
  git submodule status

  # サブモジュールの削除については、「FORMS」を参照してください

Workflow for an artificially split repo

  # 関連するコマンドの再帰(recursion)を有効にし、
  # 対象のコマンドがデフォルトでサブモジュールで再帰処理するようにします
  git config --global submodule.recurse true

  # 他のほとんどのコマンドとは異なり、
  # cloneには独自の再帰フラグが必要です:
  git clone --recurse <URL> <directory>
  cd <directory>

  # (ソース)コードを知る為に取得する
  git grep foo
  git ls-files --recurse-submodules
Note
git ls-files もまた、それ独自の --recurse-submodules フラグが必要です。
  # 新しいコードを得る
  git fetch
  git pull --rebase

  # 作業ツリーの変更
  git checkout
  git reset

Implementation details

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

SEE ALSO

GIT

Part of the git(1) suite