有没有办法让git自动更新子模块?

是否有一种方法在git pull完成时自动调用git submodule update(或最好是git submodule update --init) ?

寻找一个git配置设置,或一个git别名来帮助这一点。

108947 次浏览

git config --global alias.pullall '!git pull && git submodule update --init --recursive'

如果你想把参数传递给git pull,那么使用下面的代码:

git config --global alias.pullall '!f(){ git pull "$@" && git submodule update --init --recursive; }; f'

Kevin Ballard建议的别名是一个非常好的解决方案。只是抛出另一个选项,你也可以使用post-merge钩子,它只运行git submodule update [--init]

从Git 1.7.5开始,默认情况下它应该像你希望的那样自动更新子模块。

[编辑:每个注释:新的1.7.5行为是自动获取子模块的最新提交,但更新它们(在git submodule update意义上)。所以这个答案中的信息是相关的背景,但它本身并不是一个完整的答案。您仍然需要一个别名来在一个命令中提取和更新子模块。]

默认行为“按需”是每当你获取更新子模块提交的提交时更新子模块,并且这个提交还没有位于你的本地克隆中 你也可以在每次读取时更新它,或者从不更新(我假设是1.7.5之前的行为) 改变这种行为的配置选项是fetch.recurseSubmodules.

此选项既可以设置为布尔值,也可以设置为on-demand 将其设置为布尔值将改变fetchpull的行为,使其在设置为true时无条件地递归到子模块中,而在设置为false时则完全不递归。< / p >

当设置为on-demand(默认值)时,fetchpull 只有当子模块的超项目检索到更新子模块引用的提交时,才会递归到已填充的子模块中

看到的:

获取更多信息。

git fetch --recurse-submodules[=yes|on-demand|no]

您可以为git命令创建一个别名,以自动处理子模块更新。将以下内容添加到.bashrc中

# make git submodules usable
#   This overwrites the 'git' command with modifications where necessary, and
#   calls the original otherwise
git() {
if [[ $@ == clone* ]]; then
gitargs=$(echo "$@" | cut -c6-)
command git clone --recursive $gitargs
elif [[ $@ == pull* ]]; then
command git "$@" && git submodule update --init --recursive
elif [[ $@ == checkout* ]]; then
command git "$@" && git submodule update --init --recursive
else
command git "$@"
fi
}

我很惊讶没有人提到使用git钩子来做到这一点!

只需要将名为post-checkoutpost-merge的文件添加到相关存储库的.git/hooks目录中,并将以下内容放入每个文件中:

#!/bin/sh
git submodule update --init --recursive

因为你特别要求一个别名,假设你想为许多存储库拥有这个,你可以创建一个别名,它将这些添加到存储库的.git/hooks中。

Git 2.14开始,您可以使用git pull --recurse-submodules(并将其别名为您喜欢的任何名称)。

对于Git 2.15,你可以将submodule.recurse设置为true来启用所需的行为。

你可以通过运行:

git config --global submodule.recurse true

正如其他人提到的,你可以很容易地设置:

git config --global submodule.recurse true

然而,如果你像我一样,有一个更复杂的.gitconfig设置(我的主要~/.gitconfig文件使用include加载其他.gitconfig文件),并且你永远不记得如何在命令行git配置格式和.gitconfig格式之间转换,下面是如何将它添加到任何.gitconfig文件:

[submodule]
recurse = true

我如何能够获得子模块和嵌套子模块更新的唯一方法:

git submodule update --remote --merge --recursive; git submodule foreach --recursive "(git add .; git commit -m 'SubmoduleSync'; git push; git pull;);" git add .; git commit -m 'SubmodulesSynced'; git push; git pull;

由于括号,我努力通过终端创建别名,所以我必须手动将此添加到.gitconfig全局:

[alias] supdate = "!git submodule update --remote --merge --recursive; git submodule foreach --recursive '(git add .; git commit -m 'SubmoduleSync'; git push; git pull;);' git add .; git commit -m 'SubmodulesSynced'; git push; git pull;"

对于如何自动运行命令或别名有什么建议吗?

从Git 2.15开始,你可以设置submodule。递归为true以启用所需的行为。

事实上,你不需要这么做。

在Git 2.34 (Q4 2021)之前,在“git clone --recurse-submodules"(man)”之后,所有子模块都被克隆了,但默认情况下它们不会被其他命令递归。

在Git 2.34和submodule.stickyRecursiveClone配置设置中,submodule.recurse配置在由"clone"创建的存储库中设置为true;与“--recurse-submodules"选择。

参见提交48072 e3 (14 Aug 2021) by Mahi Kolla (24mahik)
(由Junio C Hamano—gitster提交6 d09fc5中合并,10 Sep 2021)

clone:设置子模块。如果子模块,递归=true。stickyRecursiveClone启用

署名:Mahi Kolla

根据目前的经验,当运行git clone --recurse-submodules(man)时,开发人员并不期望其他命令(如拉取或签出)递归地运行到活动子模块中。

然而,在这一步设置submodule.recurse=true可以通过在后续命令中不需要--recurse-submodules选项来简化工作流程。

收集更多关于开发人员在制作子模块方面的偏好数据。recurse=true将来的默认配置值,在submodule.stickyRecursiveClone标志的opt下部署此特性。


警告:使用Git 2.37 (Q3 2022):

没有--recurse-submodules=<arg>(man)错误地使submodule.recurse优先于fetch.recurseSubmodules,这已在Git 2.37 (Q3 2022)中更正。

参见提交5819417 (10 May 2022) by Glen Choo (chooglen)
(由Junio C Hamano—gitster提交ed54e1b中合并,20 May 2022)

pull:不让submodule.recurse覆盖fetch.recurseSubmodules

< p > 报告人:Huang Zou
资助人:菲利普·布莱恩
署名:Glen Choo

修复了“__abc4”中(man)中执行取回时submodule.recurse优先于fetch.recurseSubmodules的错误(文档/config/fetch.txt说fetch.recurseSubmodules应该优先)。

通过传递"--recurse-submodules"CLI选项,而不是传递一个组合了CLI选项和配置变量的值。

换句话说,这个错误发生是因为builtin/pull.c合并了两个听起来相似但不同的概念:

  • 是否“git pull"它本身应该关心子模块,例如它是否应该在执行合并后更新子模块的工作树。
  • --recurse-submodules"的值;来传递给底层的git fetch"

因此,当设置submodule.recurse时,底层的“__abc4”(man)将被__abc2调用,覆盖fetch.recurseSubmodules的值。

另一种(更明显的)修复错误的方法是将“git pull"来理解fetch.recurseSubmodules,但建议的解决方案更好,因为:

  • 我们不会在“__abc0”中维护两个相同的配置解析实现;和git fetch"。
  • 它与由"git pull"调用的其他命令一起工作得更好;如。'git merge'(man)不会意外地尊重fetch.recurseSubmodules