如何在一行命令中使用git clone --recursive并检出所有子模块的主分支?

63

我非常喜欢这个获取带子模块的代码库的命令:

git clone git@github.com:my_user/my_repo.git --recursive

然而,当子模块到达时,它们都被设置为“无分支”,我必须手动在每个子模块上检出主分支。是否有一种递归拉取子模块并自动将分支设置为主分支的方法?

5个回答

91
在克隆包含子模块的存储库之后,以下命令将一步到位地检出所有子模块的主分支:

克隆包含子模块的存储库后,使用以下命令可一次检出所有子模块的主分支:

git submodule foreach --recursive git checkout master

这正是我在更新vim vundle目录中的子模块时正在寻找的。 - Nolan Nichols
你可以将此命令添加到你的个人 .gitconfig 或者仓库的 .git/config 中作为一个别名 [alias],以便获得更多收益! - Ray Foss

75
怎么样:
git submodule update --init --recursive

初始化所有子模块以及所有嵌套的子模块。不确定是否会检出主分支。


2
谢谢。它没有检出主分支,只是所有的子模块!(这正是我想要的) - vulcan raven
6
使用git submodule foreach --recursive git checkout master命令可以检出每个子模块的主分支。 - randomness2077

26

问题是为什么要checkout主分支。你的子模块被固定到一个特定的sha,这也是为什么子模块克隆会被固定到那个特定提交的原因。如果不指向一个特定的sha,外部仓库很容易破坏你的构建。这绝对不是你想要的。最好有意识地进行更新。构建应该是可重复的,并且尽可能稳定。


1
我同意这一点,但这真的很烦人。如果特定的提交属于一个分支,为什么不能在此分支上以特定的提交检出子模块? - Savageman
4
因为提交 ID 是固定的,而分支可能会移动。它们是两个不同的概念,并且可以指向子模块的两个不同快照。 - vocaro
1
作为一个例子:我的团队和我使用一个子模块的中央仓库,作为一种“超级”存储库,以收集所有较小、相关的模块存储库来本地构建整个项目。这样可以节省手动下载15个以上不同存储库的麻烦,特别是如果您想将您的环境移动到另一台机器、vm等。 - Streetfights
1
十年过去了,这仍然是相关的。 - contributorpw

11

如已回答

git submodule foreach --recursive git checkout master

能够在主分支master上工作。

但如果这是一个不在所有子模块中都存在的分支,可以使用

git submodule foreach --recursive "git checkout branchname || true"
否则,如果第一个仓库没有指定的分支,命令将失败。

1
执行10次 git submodule foreach --recursive "git checkout master || git checkout main"。谢谢疯狂觉醒的人们。 - ili

7
也许你应该考虑使用gitslave作为git-submodule的替代方案,具体取决于你的开发工作流程,它可能更好(或更差)。特别是针对你的问题,gitslave将超级项目的所有成员保持在同一个分支上(除非使用特定的git(而不是gitslave)命令进行其他操作,即使这样,许多命令也会在你处于不同分支时发出警告)。
当你同时控制和开发子项目以及超级项目,并且通常希望同时标记、分支、推送、拉取等所有存储库时,Gitslave很有用。
当你无法控制子项目或更具体地希望将子项目固定在特定版本,即使子项目发生更改时,git-submodule更好。

是否可以指定需要同步哪些子模块,哪些不需要?即排除某些子模块不受此行为影响? - Savageman
@Savageman:使用gitslave时,在一组从机上执行命令时,有几种方法可以执行子集选择:正则表达式、包含子集的文件等。使用git-submodule似乎可以通过在命令行上显式命名每个子模块来实现,但我还没有尝试过。 - Seth Robertson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接