克隆具有很多子模块的git仓库需要非常长的时间。以下示例中有约100个子模块。
git clone --recursive https://github.com/Whonix/Whonix
Git会一个一个地克隆它们。这比所需时间要长得多。让我们做出(可能的)假设,即客户端和服务器都有足够的资源来同时响应多个(并行)请求。
如何使用 git clone --recursive
加速/并行下载git子模块?
克隆具有很多子模块的git仓库需要非常长的时间。以下示例中有约100个子模块。
git clone --recursive https://github.com/Whonix/Whonix
Git会一个一个地克隆它们。这比所需时间要长得多。让我们做出(可能的)假设,即客户端和服务器都有足够的资源来同时响应多个(并行)请求。
如何使用 git clone --recursive
加速/并行下载git子模块?
在 git 2.8(Q12016)中,您将能够并行启动子模块的提取!
请查看提交fbf7164(2015年12月16日),作者为Jonathan Nieder(artagnon
)。
请查看提交62104ba, 提交fe85ee6, 提交c553c72, 提交bfb6b53, 提交b4e04fb, 提交1079c4b(2015年12月16日),作者为Stefan Beller(stefanbeller
)。
(由Junio C Hamano -- gitster
--于提交187c0d3中合并,日期为2016年1月12日)
git fetch --recurse-submodules
”。git fetch
有了新选项:-j, --jobs=<n>
示例:
git fetch --recurse-submodules -j2
这个新功能的主要内容在提交c553c72(2015年12月16日)由Stefan Beller (stefanbeller
)完成。
run-command
:添加异步并行子进程处理器
这允许在stderr上有序输出的情况下并行运行外部命令。
如果我们并行运行外部命令,我们不能直接将输出管道传输到我们的stdout/err,因为它会混合。因此,每个进程的输出将通过一个缓冲区进行流式传输。一个子进程可以直接传输到我们的stdout/err以提供低延迟反馈给用户。
git fetch --jobs=<n>
”在获取子模块时允许使用<n>
个并行作业,但这不适用于从多个远程存储库获取的“git fetch --multiple
”。dscho
) 在2019年10月05日提交)。gitster
--在commit d96e31e中合并,2019年10月15日)
fetch
: 让--jobs=<n>
同样可以并行处理--multiple
签署者: Johannes Schindelin
到目前为止,
--jobs=<n>
只能并行处理子模块的获取/克隆,并不能处理--multiple
获取,这是不直观的,因为选项名称并没有特别提到子模块。让我们改变这一点。
通过这个补丁,也会并行获取多个远程仓库。为了向后兼容(并为了准备子模块和多远程仓库获取可能需要不同的并行限制的用例):
- 配置设置
submodule.fetchJobs
仍然只控制git fetch
的子模块部分,- 而新引入的设置
fetch.parallel
控制两者(但可以使用submodule.fetchJobs
覆盖子模块部分)。
git pull
并行多个远程仓库,该版本修复了使用 git fetch --jobs=0
时的一个错误。#! /usr/bin/env python
# coding: utf-8
from __future__ import print_function
import os
import subprocess
jobs=16
modules_file = '.gitmodules'
packages = []
if not os.path.exists('Whonix/' + modules_file):
subprocess.call(['git', 'clone', 'https://github.com/Whonix/Whonix'])
os.chdir('Whonix')
# get list of packages from .gitmodules file
with open(modules_file) as ifp:
for line in ifp:
if not line.startswith('[submodule '):
continue
package = line.split(' "', 1)[1].split('"', 1)[0]
#print(package)
packages.append(package)
def doit():
p = subprocess.Popen(['parallel', '-N1', '-j{0}'.format(jobs),
'git', 'submodule', 'update', '--init',
':::'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
res = p.communicate('\n'.join(packages))
print(res[0])
if res[1]:
print("error", res[1])
print('git exit value', p.returncode)
return p.returncode
# sometimes one of the updates interferes with the others and generate lock
# errors, so we retry
for x in range(10):
if doit() == 0:
print('zero exit from git after {0} times'.format(x+1))
break
else:
print('could not get a non-zero exit from git after {0} times'.format(
x+1))
在同一系统上,我将时间缩短到了45秒(我没有进行多次运行以平均波动)。
为了检查事情是否正常,我将检出的文件与以下内容进行了“比较”:
find Whonix -name ".git" -prune -o -type f -print0 | xargs -0 md5sum > /tmp/md5.sum
在同一目录下
md5sum -c /tmp/md5sum
git submodule foreach
命令速度慢的问题。为此,您可以使用parallel foreach submodule。您可以参考这个答案:https://dev59.com/j6rka4cB1Zd3GeqPkNyD#50178665 - RDCH106
git fetch --recurse-submodules -j2
并行获取子模块。请参见下面的答案。 - VonC