该选项主要用于获取所有子模块提交,而不仅仅是像主分支一样拉取一个特定的分支,原因在于下面两个提交详细说明:(注意,在Git 2.11中修复了一个错误,请参见本答案末尾)
对于
git pull
,此选项是在
提交7dce19d,2010年11月,git 1.7.4-rc0中引入的:
fetch
/pull
: 添加--recurse-submodules
选项
直到现在,你必须调用"
git submodule update
"(不带
-N|--no-fetch
选项)或类似"
git submodule foreach git fetch
"的命令来从远程获取已填充子模块中的新提交。这可能会导致在超级项目中获取或拉取新提交后,在"
git diff --submodule
"(由"
git gui
"和"
gitk
"使用)的输出中出现"
(commits not present)
"消息,并且对于实现子模块的递归检出是一个障碍。
此外,"
git submodule update
"无法在断开连接时获取更改,因此很容易忘记在断开连接之前获取子模块更改,只有在后来发现它们是必需的时才能发现。
此补丁添加了"
--recurse-submodules
"选项,以递归地从子模块的
.git/config
配置的url中获取每个填充的子模块,该选项将在每次"
git fetch
"的末尾或在超级项目中执行"
git pull
"期间使用。子模块路径来自索引。
提交 88a2197(2011年3月,git 1.7.5-rc1)解释得更详细:
fetch
/pull
:必要时递归到子模块中
为了能够访问由超级项目引用的所有填充子模块的提交,只有在超级项目记录了新提交时,才需要让“git fetch”递归到子模块中。当使用“--submodule”选项执行“git diff”时(自1.6.6起,“git gui”和“gitk”使用此选项),拥有这些提交非常有用,因为可以访问创建描述性输出所需的所有子模块提交。此外,合并子模块提交(自1.7.3以后添加)取决于相关的子模块提交是否存在。最后但并非最不重要的是,这使得在使用子模块时可以进行断开连接的操作,因为所有必要的提交都将被自动获取,以便成功地执行“git submodule update -N”。因此,我们选择将此模式作为fetch和pull的默认模式。
git pull origin master --recurse-submodules
git submodule foreach git pull origin master
第一个应该拉取而不仅仅是获取,并且与第二个等效。也许这是一个参数顺序问题:
git pull --recurse-submodules origin master
然而,这并不是更新给定分支的子模块的推荐方法:请参见下一节。
请注意,实际从主分支拉取的正确方法是
将主分支注册为子模块,使该子模块跟踪主分支:
git config -f .gitmodules submodule.<path>.branch <branch>
那么一个简单的 git submodule update --remote --recursive
就足够了。
而要获取/拉取的分支记录在父仓库中(在 .gitmodules
文件中),所以你甚至不必记住你想让子模块更新到哪个分支。
更新 Git 2.11 (2011 年第四季度)
当一个子模块的“.git
”存储库损坏时,会导致一些递归进入子模块的命令无限循环。
请参见提交 10f5c52(由Junio C Hamano (gitster
)于 2016 年 9 月 1 日提交)。
(由Junio C Hamano -- gitster
--合并于提交 293c232,2016 年 9 月 12 日)
这最后的2016次提交是在Git 2.21 (2018年第四季度)中扩展的: "git fetch --recurse-submodules
"(man)可能无法获取与超级项目绑定的必要提交,这正在得到纠正。
请看
commit be76c21 (2018年12月6日), 以及
commit a62387b,
commit 26f80cc,
commit d5498e0,
commit bcd7337,
commit 16dd6fe,
commit 08a297b,
commit 25e3d28,
commit 161b1cf (2018年11月28日),作者为
Stefan Beller (stefanbeller
).
(由Junio C Hamano -- gitster
--于commit 5d3635d合并,2019年1月29日)
submodule.c
: 在子模块的git目录中获取内容,而不是在工作树中获取
由Stefan Beller签署
保留
10f5c52656中介绍的属性 ("
submodule
: avoid auto-discovery in
prepare_submodule_repo_env()
", 2016-09-01, Git v2.11.0-rc0 --
merge listed in
batch #1),通过固定子模块的
git
目录来实现。
但是... "git fetch
"(man) 在嵌套的子模块中无法正确工作,其中最内层不感兴趣的子模块在上游进行了更新,这已经在Git 2.30(2021年第一季度)得到了纠正。
请看提交 1b7ac4e(2020年11月12日)由Peter Kaestle (dscho
)进行。
(由Junio C Hamano -- gitster
--在提交d627bf6中合并,2020年11月25日)
子模块
:修复非初始化子仓库获取的回归问题
签署者:Peter Kaestle
一项回归被
a62387b 引入了 ("
submodule.c
: fetch in submodules git directory instead of in worktree", 2018-11-28, Git v2.21.0-rc0 --
merge listed in
batch #4)。触发它的场景是当一个远程仓库中有一个嵌套的子仓库,例如这样:
superproject/middle_repo/inner_repo
。个人 A 和 B 都克隆了它,但是个人 B 没有使用
inner_repo
,因此没有在他的工作副本中初始化它。现在,个人 A 对
inner_repo
进行了更改,并通过
middle_repo
和超级项目进行了传播。一旦个人 A 推送了更改,个人 B 想要在超级项目级别上使用 "
git fetch
"
(man) 获取它们,B 的
git
(man) 调用将返回错误,说:“无法访问子模块 '
inner_repo
',在获取子模块时出错:> middle_repo”。预期情况是,在这种情况下,内部子模块将被识别为未初始化的子仓库,并且将被
git fetch
(man) 命令跳过。在 '
a62387b ("
submodule.c
: fetch in submodules git directory instead of in worktree", 2018-11-28, Git v2.21.0-rc0 --
merge listed in
batch #4)' 之前,这个功能正常工作。从
a62387b 开始,代码想要在
.git/modules
中评估
"is_empty_dir()
",对于一个只存在于工作树中的目录,当然会返回错误的返回值。此补丁撤消了
a62387b 的更改,并引入了回归测试。
警告:早期尝试修复 "git fetch --recurse-submodules
"(man) 破坏了另一个使用情况;在找到更好的解决方案之前,请使用 Git 2.30(2021年第一季度)将其恢复。
请看提交 7091499(2020年12月2日)由Junio C Hamano (gitster
)提交。
(合并于提交 f3e5dcd,作者为Junio C Hamano -- gitster
--,时间为2020年12月3日)
撤销“子模块”
:修复对未初始化的子子仓库获取的回归问题
这是一个回滚操作,提交 1b7ac4e6d4d490b224f5206af7418ed74e490608被撤销。Ralf Thielow报告说使用设置了submodule.recurse
的(手册)git fetch
可能会导致子模块被错误地无限递归获取。
在Git 2.30.1(2021年第一季度)中, "git fetch --recurse-submodules
"(man)修复了问题(第二次尝试)。
查看 提交505a276 (2020年12月9日) 由 Peter Kaestle (dscho
) 提交。
(合并自 Junio C Hamano -- gitster
-- 在 提交c977ff4,2021年1月6日)
子模块
: 修复获取未初始化的子仓库时的回归问题
签名:Peter Kaestle
抄送:Junio C Hamano
抄送:Philippe Blain
抄送:Ralf Thielow
抄送:Eric Sunshine
评审者:Philippe Blain
一个回归错误由
a62387b引入(“
submodule.c
:在子模块git目录中获取而不是在工作树中获取”,2018年11月28日,Git v2.21.0-rc0--
合并列在
批次#4中)。
触发它的情况是当一个仓库有一个子模块内嵌在另一个子模块中时,就像这样:
superproject/middle_repo/inner_repo
人员A和B都拥有它的克隆版本,而人员B没有使用
inner_repo
,因此在他的工作副本中没有初始化它。
现在,人员A引入了对
inner_repo
的更改,并通过
middle_repo
和超级项目传播它。
一旦人员A推出更改,人员B想要使用“
git fetch
”
(手册)在超级项目级别上获取它们,B的git调用将返回错误,说:
无法访问子模块'
inner_repo
',子模块获取期间出错:middle_repo
预期情况是,在这种情况下,内部子模块将被识别为未初始化的子模块,并被
git fetch
命令跳过。
这在'
a62387b(“
submodule.c
:在子模块git目录中获取而不是在工作树中获取”,2018年11月28日,Git v2.21.0-rc0--
合并列在
批次#4中)之前可以正常工作。
从
a62387b开始,代码希望在
.git/modules
内评估
"is_empty_dir()
",对于只存在于工作树中的目录,然后提供错误的返回值。
此补丁通过连接实际的工作树和未初始化子模块的名称来确保
is_empty_dir()
获得正确的未初始化子模块路径。
第一次尝试修复这个回归错误,在
1b7ac4e("
submodules
: fix of regression on fetching of non-init subsub-repo",2020年11月12日,Git v2.30.0-rc0--
合并列在
批次#8中),通过简单地恢复
a62387b,导致了在未初始化子模块的情况下递归获取超级项目时无限循环获取子模块,因此该提交在
7091499中被撤消(Revert "
submodules
: fix of regression on fetching of non-init subsub-repo",2020年12月2日,Git v2.30.0-rc0--
合并列在
批次#10中)。
为了防止未来的故障,还要为此场景添加回归测试。
"git
fetch --recurse-submodules
from``"(man) 是用于从多个远程仓库 (可以是一个远程组或"--all") 中获取子模块内容的命令。在 Git 2.37 (Q3 2022) 版本中,修复了在子模块中使用该命令时会造成额外的 "git fetch
"(man) 的问题。
请查看提交 0353c68(2022年5月16日)由Junio C Hamano(gitster
)提交。
(已合并Junio C Hamano -- gitster
--在提交fa61b77中,2022年5月25日)
fetch
:不要从子模块运行冗余的获取操作
评审者:Glen Choo
注意:本翻译仅供参考,如有不妥之处请联系专业人士核对。
当
7dce19d(“
fetch/pull
: Add the
--recurse-submodules
option”,2010-11-12,Git v1.7.4-rc0 --
merge)引入了“--recurse-submodule”选项时,采取的方法是仅在所有主要获取(通常可以从单个远程获取,但也可以使用
fetch_multiple()
从一组远程获取)成功后执行子模块中的获取操作。
稍后我们添加了“--all”以从所有定义的远程获取,这使事情变得更加复杂。
如果您的项目有一个子模块,并尝试运行“git fetch
”(man)--recurse-submodule
--all,则会看到顶级获取操作,该操作会调用另一个获取操作以获取子模块,然后再获取相同的子模块。
除了子模块的最后一个获取操作外,其余获取操作都来自通过fetch_multiple()
接口生成的“git fetch --recurse-submodules
”(man)子进程,而最后一个获取操作来自代码末尾。
由于每次在fetch_multiple()
中为顶级执行递归获取子模块,因此子模块中的最后一个获取操作是冗余的。
仅当fetch_one()
与顶级的单个远程交互时才重要。
顺便说一下,在处理一组远程时存在一种优化,但在使用“--all”时缺少该优化。
在前者中,当该组变为一个时,我们使用正常的fetch_one()
代码路径,而不是通过fetch_multiple()
接口生成“git fetch
”作为子进程。
如果发现我们只定义了一个远程,则在处理“--all”时也执行相同的操作。
jhowtan
)提交。 (由Junio C Hamano --gitster
--于2021年10月6日合并至commit 921c795)。 - VonC