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

名前

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

概要

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

説明

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

ファイルシステム上では、サブモジュールは通常 (常にではありません - 下記の「形式」を参照) (i) スーパープロジェクトの $GIT_DIR/modules/ ディレクトリの下にある Git ディレクトリ、(ii) スーパープロジェクトのワーキングディレクトリ内にあるワーキングディレクトリ、および (iii) サブモジュールのワーキングディレクトリのルートにある、(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 があります。例として grepcheckout があります。一部のコマンドは、fetchpush のように列挙型を受け入れ、サブモジュールがどのように影響を受けるかを指定できます。

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

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

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

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

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

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

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

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

形式

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

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

  • "古い形式" のサブモジュール: 埋め込まれた .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>.activetrue に設定されている場合

    または

  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 のパススペックで除外されている場合、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* を除くすべてのサブモジュールが、.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