【问题标题】:What are the drawbacks to setting git's submodule.recurse config option to true?将 git 的 submodule.recurse 配置选项设置为 true 有什么缺点?
【发布时间】:2018-11-28 07:49:14
【问题描述】:

这个问题Is there a way to make git pull automatically update submodules? 有一个像这样配置 git 的公认答案:

git config --global submodule.recurse true

就像那个答案的 cmets 之一,我想知道为什么这不是 git 的默认行为;更准确地说,设置此配置选项有什么缺点?

【问题讨论】:

  • IMO,您不应该总是希望自动更新子模块,因为它们可能会在开发时破坏您的应用程序。一旦我确定我的代码,我宁愿更新它们。如果这是默认行为,那可能会让我很难调试。
  • @Brewal 您能否详细说明他们如何“在开发时破坏您的应用程序”?自动更新子模块并不意味着将它们更新到最新版本。这意味着将它们更新为父存储库指定的提交哈希。在开发过程中,子模块应该是稳定的。相反,如果子模块与父存储库所期望的不同步,更新它们可能会破坏事情。
  • @jamesdlin 我的意思是,如果您在子模块中有您关心的本地更改,那么使用这种配置可以武装您的本地开发,因为不知道拉动做了什么;而在拉动时使用 explicit 标志可确保您知道自己在做什么。这对 IMO 很重要,因为并非所有在您的存储库上工作的开发人员都会捕捉到这种设置。
  • 我看不出子模块有什么不同。拉取任何存储库都有可能破坏未提交的本地更改,不是吗?

标签: git git-submodules


【解决方案1】:

这个选项是在commit 046b482 中引入的,最初用于工作树 操作命令(read-tree/checkout/reset

git grep/fetch/pull/push 紧随其后。
但是,作为the documentation mentions,与下面的其他命令不同,clone 仍然需要自己的递归标志:git clone --recurse-submodules <URL> <directory>
看到这个recent discussion

这是一个设计决定,因为 git clone 可能太大了。
如果设置了submodule.recurse,也许我们需要重新考虑该决定并克隆子模块。

由于涉及的子模块的数量/大小可能很大,因此目前的默认行为是默认不递归地包含它们。

它们的主要缺点是必须在每个子模块(以及它们各自的子模块)中递归地引入可能的时间开销。
如果您有很多,并且不需要全部,最好关闭该选项,并在需要时指定--recursive

然而,一个优点是在切换分支时避免看到“未跟踪的文件”as seen in this discussion


警告,从 Git 2.34(2021 年第四季度)开始,git clone --recurse-submodules,意味着一个简单的git pull 将递归到子模块中。

即使git config --global submodule.recurse没有设置。

参见“Is there a way to make git pull automatically update submodules?”。

【讨论】:

【解决方案2】:

我最近回到recurse=false有两个原因:

  • 我有我的项目需要的子模块(来自 github 的第 3 方库),但它们有我不需要的子模块。即 - 几个实例o gtest。我不为 3rd 方库构建测试,所以获取它们是浪费时间和空间
  • 如果子模块远程在 repo 中更改,我会遇到问题。这通常发生在我决定库需要一些修改并且推送到上游是不可行的时候。我并没有真正研究它,因为从头开始克隆总是比弄乱子模块更容易。 recurse=false 似乎已经缓解了它,但同样:我没有完全调查这个问题。

【讨论】:

    【解决方案3】:

    事情是这样的:人们倾向于采用默认设置,除非他们的工作流无法正确运行,而且 Git 的复杂性是 imho 完全由于它支持的工作流多样性。

    您的工作流程会因您是否在供应商基础上携带补丁而有很大差异(这也取决于是在您的顶级存储库还是一个或多个子模块中)、您尝试对代码执行的操作(开发新功能?测试升级?只是简单的获取和构建?),项目的设置(构建每个配置是否总是需要所有子模块?将可选功能分成单独的历史可以带来巨大的回报),一切。

    因此,在我看来,调用与您正在使用的工作流匹配或不匹配的默认值是一个“缺点”,似乎是只见树木不见森林。无论出厂默认值是如何设置的,至少在某些存储库中,它们对于您的工作流可能不是最理想的,这正是因为 Git 服务的工作流种类繁多。使默认值适合您,其他人会出现问他们为什么默认递归获取所有内容。

    我唯一可以明确地将自动递归设置为默认设置的缺点是:鉴于任何人都可以猜测该设置是否会匹配任何特定 repo 中的工作流,并且出厂默认设置必须是猜测,猜测更昂贵的选择更糟糕。

    为您的所有工作打开自动递归配置很容易,但如果您甚至不需要这样做,您可能会浪费大量时间进行克隆,您根本不知道根本不需要。大型共享供应商历史的本地前端或参考仓库很容易。

    【讨论】:

      【解决方案4】:

      当克隆或拉取包含子模块的存储库时 默认情况下不会签出子模块;您可以指示克隆 递归到子模块。 git 的 init 和 update 子命令 子模块将维护已签出的子模块并在适当的位置 在您的工作树中进行修订。或者,您可以设置 submodule.recurse 将结帐递归到子模块中。

      来源:git-scm.com

      此选项的缺点是克隆或拉取包含多个子模块的存储库是性能成本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-26
        • 2015-02-08
        • 2012-11-15
        • 2011-01-05
        • 2021-06-29
        • 2014-03-02
        • 2011-10-29
        相关资源
        最近更新 更多