设置和配置
获取和创建项目
基本快照
分支和合并
共享和更新项目
检查和比较
打补丁
调试
邮件
外部系统
服务器管理
指南
管理
底层命令
- 2.44.1 → 2.49.0 没有变化
-
2.44.0
2024-02-23
- 2.43.1 → 2.43.6 没有变化
-
2.43.0
2023-11-20
- 2.35.1 → 2.42.4 没有变化
-
2.35.0
2022-01-24
- 2.29.1 → 2.34.8 没有变化
-
2.29.0
2020-10-19
- 2.27.1 → 2.28.1 没有变化
-
2.27.0
2020-06-01
- 2.25.1 → 2.26.3 没有变化
-
2.25.0
2020-01-13
- 2.22.1 → 2.24.4 没有变化
-
2.22.0
2019-06-07
- 2.19.3 → 2.21.4 没有变化
-
2.19.2
2018-11-21
- 2.19.1 没有变化
-
2.19.0
2018-09-10
- 2.17.0 → 2.18.5 没有变化
-
2.16.6
2019-12-06
- 2.15.4 没有变化
-
2.14.6
2019-12-06
描述
子模块是嵌入在另一个仓库中的仓库。 子模块有它自己的历史; 它嵌入在其中的仓库称为超项目。
在文件系统中,子模块通常(但并非总是 - 请参见下面的 FORMS)由以下各项组成:(i)Git 目录,位于其超项目的 $GIT_DIR/modules/
目录下;(ii)超项目工作目录内部的工作目录;以及(iii)位于子模块工作目录根目录下的 .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 的 porcelain 层提供了额外的提示。 例如,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 目录。
如果从未初始化子模块,这是找到子模块配置的唯一位置。 它用作指定从何处获取子模块的最后后备手段。
形式
子模块可以采用以下形式
-
DESCRIPTION 中描述的基本形式,具有 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_ 是由于其自身的 active 标志,所有其他子模块都是由于子模块的 active 路径规范,该规范指定任何以 _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] 套件的一部分