设置和配置
获取和创建项目
基本快照
分支和合并
共享和更新项目
检查和比较
修补
调试
电子邮件
外部系统
服务器管理员
指南
管理
底层命令
- 2.44.1 → 2.47.0 无更改
- 2.44.0 02/23/24
- 2.43.1 → 2.43.5 无更改
- 2.43.0 11/20/23
- 2.35.1 → 2.42.3 无更改
- 2.35.0 01/24/22
- 2.29.1 → 2.34.8 无更改
- 2.29.0 10/19/20
- 2.27.1 → 2.28.1 无更改
- 2.27.0 06/01/20
- 2.25.1 → 2.26.3 无更改
- 2.25.0 01/13/20
- 2.22.1 → 2.24.4 无更改
- 2.22.0 06/07/19
- 2.19.3 → 2.21.4 无更改
- 2.19.2 11/21/18
- 2.19.1 无更改
- 2.19.0 09/10/18
- 2.17.0 → 2.18.5 无更改
- 2.16.6 12/06/19
- 2.15.4 无更改
- 2.14.6 12/06/19
描述
子模块是一个嵌入到另一个仓库中的仓库。子模块有自己的历史记录;它嵌入到的仓库称为超级项目。
在文件系统上,子模块通常(但并非总是 - 请参阅下面的“形式”)由以下部分组成:(i)位于其超级项目的 $GIT_DIR/modules/
目录下的 Git 目录,(ii)超级项目工作目录内的工作目录,以及子模块工作目录根目录下的一个 .git
文件,指向(i)。
假设子模块在 $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
设置指定了从哪里获取子模块。
子模块至少可以用于两种不同的用例
-
在保持独立历史记录的同时使用另一个项目。子模块允许您将另一个项目的工作树包含在您自己的工作树中,同时保持两个项目的历史记录分离。此外,由于子模块固定到任意版本,因此可以独立开发另一个项目而不会影响超级项目,从而允许超级项目项目仅在需要时才能修复到新版本。
-
将(逻辑上单个的)项目拆分为多个仓库并将其重新绑定在一起。这可用于克服 Git 实现的当前限制,以获得更细粒度的访问权限
-
Git 仓库的大小:在目前的形式下,Git 在处理包含树之间未经增量计算压缩的内容的大型仓库时,扩展性较差。例如,您可以使用子模块来保存大型二进制资产,并且可以浅克隆这些仓库,这样您在本地就不会有大型历史记录。
-
传输大小:在目前的形式下,Git 要求存在整个工作树。它不允许在 fetch 或 clone 中传输部分树。如果您正在处理的项目由多个仓库组成,这些仓库作为子模块绑定到超级项目中,则可以避免提取您不感兴趣的仓库的工作树。
-
访问控制:通过限制用户对子模块的访问,这可用于为不同的用户实施读/写策略。
-
子模块的配置
可以使用以下机制(从最高到最低优先级)配置子模块操作
-
支持将子模块作为其路径规范一部分的那些命令的命令行。大多数命令都有一个布尔标志
--recurse-submodules
,用于指定是否递归进入子模块。例如,grep
和checkout
。一些命令采用枚举,例如fetch
和push
,您可以在其中指定子模块如何受到影响。 -
子模块内部的配置。这包括子模块中的
$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
条目。 -
“旧形式”子模块:具有嵌入式
.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>/
。
活动子模块
子模块被认为是活动的,
-
如果
submodule.<name>.active
设置为true
或
-
如果子模块的路径与
submodule.active
中的路径规范匹配或
-
如果
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>.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* 由于其自身的活动标志而处于活动状态,所有其他子模块由于子模块活动路径规范而处于活动状态,该规范指定任何以 *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 submodule
的 init
和 update
子命令将保持子模块检出并在工作树中处于适当的修订版本。或者,您可以设置 submodule.recurse
以使 checkout
递归进入子模块(请注意,submodule.recurse
也影响其他 Git 命令,有关完整列表,请参阅 git-config[1])。
GIT
是 git[1] 套件的一部分