如何“git clone”包括子模块?

Posted

技术标签:

【中文标题】如何“git clone”包括子模块?【英文标题】:How to "git clone" including submodules? 【发布时间】:2011-04-17 08:25:36 【问题描述】:

我正在尝试将子模块放入存储库中。问题是当我克隆父仓库时,子模块文件夹完全是空的。

有什么办法可以让git clone parent_repo 真正将数据放入子模块文件夹中?

例如,http://github.com/cwolves/sequelize/tree/master/lib/、nodejs-mysql-native 指向一个外部 git 子模块,但是当我签出 sequelize 项目时,该文件夹是空的。

【问题讨论】:

该命令将是git clone --recurse-submodules --remote-submodules(2019 年第三季度 Git 2.23):它将在一个命令中克隆和更新子模块。见my edited answer below。 有可能你想离开--remote-submodules,直接做--recurse-submodules。当心。 @BenjaminBerman 你能否详细说明为什么你不想使用git clone --recurse-submodules --remote-submodules @LiamCrowley ,由于各种原因,父(托管,包含)存储库可能依赖于子模块的特定版本。例如,主机仓库的维护者可能还没有准备好处理更新。 【参考方案1】:

在 Git 2.13 及更高版本中,可以使用--recurse-submodules 代替--recursive

git clone --recurse-submodules -j8 git://github.com/foo/bar.git
cd bar

编者注:-j8 是一种可选的性能优化,在 2.8 版中可用,一次最多可并行获取 8 个子模块 — 请参阅 man git-clone

Git 1.9 版直到 2.12 版(-j 标志仅在 2.8+ 版中可用):

git clone --recursive -j8 git://github.com/foo/bar.git
cd bar

使用 Git 1.6.5 及更高版本,您可以使用:

git clone --recursive git://github.com/foo/bar.git
cd bar

对于已克隆的存储库或较旧的 Git 版本,请使用:

git clone git://github.com/foo/bar.git
cd bar
git submodule update --init --recursive

【讨论】:

有没有办法在你的 git 存储库中将此行为指定为默认行为,以便信息较少的克隆器会自动获取初始化的子模块? @NHDaly 很遗憾,没有。 (至少我不知道。) 逻辑上认为 git clone --recursive 也会填充子模块的任何子模块,对吧? 我想我每个月都会回到这个答案...为什么 git 在克隆时不询问它是否也应该下载子模块? 还要说明一下(因为我想知道但除了查看源代码外找不到答案), git clone --recursive--recurse-submodules 选项的行为相同。它们导致调用相同的函数。【参考方案2】:

在填充子模块之前,您必须做两件事:

git submodule init 
git submodule update

【讨论】:

我很害怕......这没有任何意义,因为在这种情况下你正在检查一个部分项目。我知道子模块更新不是自动的,但是为什么绑定的版本没有自动签出?有什么办法可以强制吗?我有一个包含 3 级子模块的项目,为了结帐而必须遍历那么远似乎很荒谬。 请阅读 git-submodule(1) 手册页 (kernel.org/pub/software/scm/git/docs/git-submodule.html)。你会发现git submodule update 支持一个很好的参数,叫做--recursive 为什么不在一个命令中同时执行这两个操作呢? git submodule update --init(另见my answer)。 我觉得用这两个命令回答这个问题比较好。它更好地解释了如何完成任务。 @MathiasBynens 我刚刚登录的一台机器只有 git 1.5.5.6,它显然不支持缩短指令,但支持它作为两个命令。【参考方案3】:

Git 2.23(2019 年第三季度):如果您想克隆 将子模块更新到最新版本:

git clone --recurse-submodules --remote-submodules

如果您只是想以他们记录的 SHA1 克隆它们:

git clone --recurse-submodules

见下文。

请注意,Git 2.29(2020 年第四季度)对子模块处理进行了重大优化。

参见 Orgad Shaneh (orgads) 的 commit a462bee(2020 年 9 月 6 日)。(由 Junio C Hamano -- gitster -- 合并于 commit 2ce9d4e,2020 年 9 月 18 日)

submodule: 禁止检查文件名和对象 ID 的引用歧义

签字人:Orgad Shaneh

collect_changed_submodules() 的 argv 参数仅包含对象 id(所有 ref 的对象引用)。​​

通过assume_dashdash, 通知setup_revisions() 输入不是文件名,这样可以避免每个引用的冗余统计信息。

同时抑制refname_ambiguity 标志以避免对每个对象进行文件系统查找。类似的逻辑可以在 cat-file、pack-objects 等中找到。

此更改将我的 repo 中 git fetch(man) 的时间从 25 秒缩短到 6 秒


2010 年原始答案

正如 joschi 在 cmets 中提到的,git submodule 现在支持 --recursive 选项(Git1.6.5 及更高版本)。

如果指定--recursive,此命令将递归到已注册的子模块中,并更新其中的任何嵌套子模块。

有关初始化部分,请参阅 Working with git submodules recursively。 请参阅 git submodule explained 了解更多信息。

使用 1.6.5 及更高版本的 git,您可以通过使用 –-recursive 选项克隆超级项目来自动执行此操作:

git clone --recursive git://github.com/mysociety/whatdotheyknow.git

2016 年更新,使用 git 2.8:请参阅“How to speed up / parallelize downloads of git submodules using git clone --recursive?”

您可以使用多个线程并行启动获取子模块。 例如:

git fetch --recurse-submodules -j2

更好的是,使用 Git 2.23(2019 年第三季度),您可以通过一个命令将子模块克隆并签出到其跟踪分支!

参见Ben Avison (bavison)commit 4c69101(2019 年 5 月 19 日)。(由 Junio C Hamano -- gitster -- 合并于 commit 9476094,2019 年 6 月 17 日)

clone:添加--remote-submodules标志

使用 git clone --recurse-submodules 时,以前无法 将--remote 开关传递给隐式git submodule update 命令 您希望在其上签出子模块的任何用例 远程跟踪分支,而不是使用超级项目中记录的 SHA-1。

这个补丁纠正了这种情况。 它实际上也将--no-fetch 传递给git submodule update,因为子模块刚刚被克隆,因此再次从远程获取只会减慢速度。

这意味着:

--[no-]remote-submodules:

所有被克隆的子模块将使用子模块的远程跟踪分支的状态来更新子模块,而不是超级项目记录的 SHA-1。相当于将--remote 传递给git submodule update

【讨论】:

所以 Git 花了 14 年才开始为子模块添加适当的支持,呵呵。感谢更新!如果我已经有一个没有子模块且没有记录 SHA1 的主仓库的克隆,并且我想提取每个子模块的最新版本怎么办。可行吗? @VioletGiraffe 如果该克隆存储库具有子模块,则它具有“记录的 SHA1”。 git submodule update --init --recursive --remote 应该将它们更新为各自分支的最新提交。 (例如:***.com/a/56981834/6309) 让我用一个例子来澄清一下:我在 Github 上有一个使用子模块的模板项目,我什至将子模块的特定修订提交到这个模板仓库中。但是当我从这个 repo 创建一个新项目时,你列出的命令(clone --recurse-submodules --remote-submodulessubmodule update --init --recursive --remote 都没有)让我真正获取 subrepos。我得到的只是一个 .gitmodules 文件,除了手动克隆它们之外,我找不到任何方法来初始化子存储库。我想至少有一个脚本来使用submodule foreach... 如果您知道解决方案,我会问一个您可以回答的单独问题。这是测试仓库,除了手动之外我找不到任何方法来初始化:github.com/VioletGiraffe/TEST @VioletGiraffe 那是因为您已经添加并提交了 .gitmodules 而不是 gitlink(***.com/a/16581096/6309,索引中的特殊条目:***.com/a/19354410/6309)这是一个具有正确 gitlink 的存储库注册:github.com/tiagomazzutti/antlr4dart【参考方案4】:

[快速解答]

你可以使用这个命令来克隆你的 repo 和所有的子模块:

git clone --recursive YOUR-GIT-REPO-URL

或者如果你已经克隆了项目,你可以使用:

git submodule init
git submodule update

【讨论】:

在 git 版本 2.24.3 上,上面的命令给了我错误:错误:服务器不允许请求未公布的对象 e635630d55682951eb2da35630d5da15b6cc 在子模块路径 'ui-library' 中获取,但它不包含 e635630d55682951eb2da35630dccda1。直接获取该提交失败。【参考方案5】:

[快速解答]

克隆父仓库(包括一些子模块仓库)后,执行以下操作:

git submodule update --init --recursive

【讨论】:

【参考方案6】:

如果您的子模块已添加到分支中,请务必将其包含在您的克隆命令中...

git clone -b <branch_name> --recursive <remote> <directory>

【讨论】:

这更像我正在寻找的......但是子模块将它们的分支列为“分离”。 :(【参考方案7】:

试试这个:

git clone --recurse-submodules

假设您已经将子模块添加到父项目,它会自动拉入子模块数据。

【讨论】:

请注意--recurse-submodules--recursive 是equivalent aliases。 @SuperUberDuper 在这种情况下,您可以按照this answer 中的说明执行git submodule update --init --recursive【参考方案8】:

我认为你可以分 3 步走:

git clone
git submodule init
git submodule update

【讨论】:

【参考方案9】:

使用此命令克隆包含所有子模块的 repo

git clone --recurse-submodules git@gitlab.staging-host.com:yourproject

更新所有子模块的代码

git submodule update --recursive --remote

【讨论】:

【参考方案10】:

迟到的答案

// git CLONE INCLUDE-SUBMODULES ADDRESS DESTINATION-DIRECTORY
git clone --recursive https://USERNAME@bitbucket.org/USERNAME/REPO.git DESTINATION_DIR

正如我刚刚花了整整一个小时和一个朋友摆弄一样:即使您对 BitBucket 拥有管理员权限,请始终克隆原始存储库并使用拥有该存储库的人的密码。很烦人发现你遇到了这个陷阱:P

【讨论】:

这正是我正在处理的问题。那么,您是说需要在具有子模块的 bitbucket 存储库上进行开发的任何人都必须使用存储库创建者的凭据?布莱赫。 @jsleuth 似乎是这样 - 这很糟糕......我知道。 这听起来像一个错误。你向 Bitbucket 报告了吗? @MathiasBynens 您是否偶然发现了这个问题?一年半过去了,其实我也不知道是不是还是这样。 它没有描述性地回答 OPs 的问题,而是详细说明了 Bitbucket 中一个不相关的错误;顺便说一句,可以将其缩写为“使用 SSH 密钥身份验证”。【参考方案11】:

您可以在克隆存储库时使用--recursive 标志。此参数强制 git 克隆存储库中所有已定义的子模块。

git clone --recursive git@repo.org:your_repo.git

克隆后,有时子模块分支可能会改变,所以在它之后运行这个命令:

git submodule foreach "git checkout master"

【讨论】:

【参考方案12】:

尝试在 git 存储库中包含子模块。

git clone -b <branch_name> --recursive <remote> <directory>

git clone --recurse-submodules

【讨论】:

【参考方案13】:

只需在您的项目目录中执行这些操作即可。

$ git submodule init
$ git submodule update

【讨论】:

如果您之前已经克隆了您的存储库,这是正确的答案。【参考方案14】:

子模块并行获取旨在通过同时获取多个存储库来减少获取存储库及其所有相关子模块所需的时间。这可以通过使用新的 --jobs 选项来完成,例如:

git fetch --recurse-submodules --jobs=4

根据 Git 团队的说法,这可以大大加快更新包含许多子模块的存储库的速度。当使用 --recurse-submodules 而没有新的 --jobs 选项时,Git 会一个一个地获取子模块。

来源:http://www.infoq.com/news/2016/03/git28-released

【讨论】:

【参考方案15】:

我在 GitHub 存储库中遇到了同样的问题。我的帐户缺少 SSH 密钥。过程是

    Generate SSH Key Adding a new SSH key to your GitHub account

然后,您可以使用子模块克隆存储库 (git clone --recursive YOUR-GIT-REPO-URL)

运行 git submodule initgit submodule update 以获取已克隆存储库中的子模块。

【讨论】:

是的,就是Permission denied (publickey). fatal: Could not read from remote repository.错误【参考方案16】:

如果它是一个新项目,你可以这样做:

$ git clone --recurse-submodules https://github.com/chaconinc/YourProjectName 

如果已经安装了:

$ cd YourProjectName (for the cases you are not at right directory) 
$ git submodule init
$ git submodule update

【讨论】:

【参考方案17】:

试试这个。

git clone -b <branch_name> --recursive <remote> <directory>

如果您在分支中添加了子模块,请确保将其添加到克隆命令中。

【讨论】:

【参考方案18】:
git submodule foreach git pull origin master

【讨论】:

以上是关于如何“git clone”包括子模块?的主要内容,如果未能解决你的问题,请参考以下文章

git clone

如何捕获从 python 子进程运行的 git clone 命令的输出

git clone 后使用子分支

使用Capistrano 3部署git子模块

Esky 不包括子模块

Git子模块添加:“在本地找到一个git目录”问题