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つの異なるユースケースに使用できます:
-
独立した履歴を維持しながら別のプロジェクトを使用。サブモジュールを使用すると、両方のプロジェクトの履歴を分離したまま、あなた独自の作業ツリー内に別のプロジェクトの作業ツリーを含めることができます。また、サブモジュールは任意のバージョンに固定できるため、別のプロジェクトは、スーパープロジェクトに影響を与えることなく独立して開発でき、スーパープロジェクトプロジェクトが必要とした場合にのみ別プロジェクトを新しいバージョンに固定できます。
-
(論理的に単一の)プロジェクトを複数のリポジトリに分割し、それらを結び付けます。これを使用して、Gitの実装の現在の制限を克服し、よりきめ細かいアクセスを実現できます:
- Gitリポジトリのサイズ
-
現在の形式では、 Gitは、ツリー間のデルタ計算によって圧縮されていないコンテンツを含む大規模なリポジトリーではスケールアップが十分にできません。 たとえば、あなたはサブモジュールを使用して大きなバイナリ・アセットを保持し、 これらのリポジトリーを浅く複製(shallow clone)して、 ローカルに巨大な履歴を持たないようにすることができます。
- 転送サイズ
-
現在の形式では、Gitは作業ツリー全体が存在する必要があります。 部分的なツリーをフェッチまたはクローンで転送することはできません。 あなたが作業しているプロジェクトが、 スーパープロジェクトのサブモジュールとして結合された複数のリポジトリで構成されている場合は、 関心のないリポジトリの作業ツリーをフェッチすることを回避できます。
- アクセス制御
-
サブモジュールへのユーザーアクセスを制限することにより、 さまざまなユーザーの読み取り/書き込みポリシーを実装できます。
The configuration of submodules
サブモジュール操作は、以下のメカニズムを使用して構成(configure)できます(優先順位の高い順です):
-
パススペックの一部としてサブモジュールを使用することをサポートするコマンドのコマンドライン。 ほとんどのコマンドには、サブモジュールに再帰するかどうかを指定するブールフラグ
--recurse-submodules
があります。 例としては、grep
やcheckout
があります。fetch
やpush
などの一部のコマンドは、サブモジュールがどのように影響を受けるかを指定できる列挙型を取ります。 -
サブモジュール内の構成。 これには、サブモジュール内の
$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
サブモジュールがアクティブと見なされるには、
-
if
submodule.
<name>.active
がtrue
に設定されているor
-
if サブモジュールのパスが
submodule.active
のパススペックと一致するor
-
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
上記の構成では、サブモジュール bar
と baz
のみがアクティブになります。 bar
は上記(1)により、 baz
は上記(3)によりアクティブになります。 (1)が(3)よりも優先されるため、 foo
は非アクティブです。
上記(1)と(2)でサブモジュールがアクティブでないことを指定している場合は、(3)は歴史的遺物であり、無視されることに注意してください。 つまり、 submodule.
<name>.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 はそれ自体のアクティブフラグによるものであり、他のすべては 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」を参照してください
人為的に分割されたリポジトリーのためのワークフロー
# 関連するコマンドの再帰(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
サブモジュールを含むリポジトリーをクローンまたはプルする際、 デフォルトではサブモジュールはチェックアウトされません。 clone
コマンドにサブモジュールへの再帰を指示することが可能です。 git
submodule
の init
および update
サブコマンドは、 サブモジュールを作業ツリー内でチェックアウトし、 適切なリビジョンに保ちます。 あるいは、 submodule.recurse
を設定することで、 checkout
がサブモジュールに再帰するようにできます(なお、 submodule.recurse
は他の Git コマンドにも影響を与えるため、 完全なリストは git-config(1) を参照してください)。
SEE ALSO
GIT
Part of the git(1) suite