## Name

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/`，那么超级`gitlink`项目通过表单的树中的`path/to/bar`一个入口和其`.gitmodules`文件中的一个入口（请参阅gitmodules [5]）来跟踪子模块`submodule.foo.path = path/to/bar`。

该`gitlink`条目包含超级项目期望子模块的工作目录所处的提交的对象名称。

所述部分`submodule.foo.*`中`.gitmodules`的文件提供了额外的提示来GITS瓷层，诸如在哪里获得经由所述子模块`submodule.foo.url`的设置。

子模块可以用于至少两种不同的使用情况：

1. 使用另一个项目同时保持独立的历史 子模块允许您在自己的工作树中包含另一个项目的工作树，同时保持两个项目的历史分离。另外，由于子模块固定为任意版本，所以其他项目可以独立开发而不会影响超级项目，只有在需要时才允许超级项目项目自行修复新版本。

2. 将一个（逻辑上单一的）项目拆分成多个存储库并将它们重新绑定在一起。这可以用来克服 Gits 实现的当前局限性，以实现更好的粒度访问：

    -  Size of the git repository: In its current form Git scales up poorly for large repositories containing content that is not compressed by delta computation between trees. However you can also use submodules to e.g. hold large binary assets and these repositories are then shallowly cloned such that you do not have a large history locally.

    -  Transfer size: In its current form Git requires the whole working tree present. It does not allow partial trees to be transferred in fetch or clone.

    -  Access control: By restricting user access to submodules, this can be used to implement read/write policies for different users.

## 子模块的配置

子模块操作可以使用以下机制进行配置（从最高到最低优先级）：

- 支持获取子模块规格的那些命令的命令行。大多数命令都有一个布尔标志，`--recurse-submodules`是否递归到子模块中。例子是`ls-files`或`checkout`。一些命令使用枚举，比如`fetch`和`push`，您可以指定子模块如何受到影响。

- 子模块内部的配置。这包括`$GIT_DIR/config`在子模块中，还包括树中的设置（如a `.gitattributes`或`.gitignore`指定子模块内命令行为的文件）。例如，`.gitignore`当您`git status --ignore-submodules=none`在超级项目中运行时，将会观察到子模块文件的影响。这通过`status`在注意其`.gitignore`文件的子模块中运行来从子模块的工作目录收集信息。子模块的`$GIT_DIR/config`文件`git push --recurse-submodules=check`在超级项目中运行时会起作用，因为这将检查子模块是否有任何未发布到任何远程的更改。遥控器在`$GIT_DIR/config`文件中像往常一样在子模块中进行配置。

- `$GIT_DIR/config`超级项目中的配置文件。在这个地方的典型配置是控制一个子模块是否通过`active`例如标志递归到所有的子模块中。如果子模块尚未初始化，那么子模块内部的配置尚不存在，因此例如在此处配置从哪里获取子模块的配置。

- `.gitmodules`超级项目中的文件。除了子模块名称和路径之间所需的映射之外，项目通常使用此文件为上游的存储库集合建议缺省值。该文件主要用作超级项目中名称和路径之间的映射，以便可以找到子模块的git目录。如果子模块从未初始化，则这是唯一可以找到子模块配置的地方。它作为最后一个回退来指定从哪里获取子模块。

## 形式

子模块可以采取以下形式：

- 描述中描述的基本形式包含 Git 目录，工作目录，`gitlink`一个`.gitmodules`条目和一个条目。

- “旧式”子模块：带有嵌入式`.git`目录的工作目录，以及超级项目中的跟踪`gitlink`和`.gitmodules`条目。这通常在使用较旧版本的 Git 生成的存储库中找到。可以手动构建这些旧的表单存储库。在取消初始化或删除（见下文）时，子模块 Git 目录会自动移动到`$GIT_DIR/modules/<name>/`超级项目。

- 去初始化子模块：A `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>/`。

## 第三方库的工作流程

    # 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 defaultgit config --global submodule.recurse true

    # Unlike the 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

    # Get new codegit fetch

    git pull --rebase

    # change worktree

    git checkout

    git reset

## 实施细节

克隆或拉取包含子模块的存储库时，默认情况下不会检出子模块; 您可以指示`clone`递归到子模块。该`init`和`update`的子命令`git submodule`将保持子模块签出，并在您的工作树适当的修订。或者，您可以设置`submodule.recurse`为`checkout`递归到子模块。