如何使用git clone --recursive加速/并行下载git子模块?

eqzww0vc  于 2023-03-21  发布在  Git
关注(0)|答案(2)|浏览(175)

克隆有很多子模块的git仓库需要很长时间。

git clone --recursive https://github.com/Whonix/Whonix

Git会一个一个地克隆它们。这比所需的时间要长得多。让我们做一个(可能的)假设,客户端和服务器都有足够的资源来同时响应多个(并行)请求。
如何使用git clone --recursive加速/并行下载git子模块?

q8l4jmvw

q8l4jmvw1#

使用git 2.8(Q12016),你将能够并行地启动子模块的获取!
参见commit fbf7164(2015年12月16日),作者Jonathan Nieder ( artagnon )
参见commit 62104bacommit fe85ee6commit c553c72commit bfb6b53commit b4e04fbcommit 1079c4b(16 Dec 2015)by Stefan Beller ( stefanbeller )
(由Junio C Hamano -- gitster --合并至commit 187c0d3,2016年1月12日)
添加一个框架来并行生成一组进程,并使用它来并行运行“git fetch --recurse-submodules”。
为此,git fetch提供了新选项:

-j, --jobs=<n>

用于提取子模块的并行子模块数。

每一个都从不同的子模块中取数,这样取多个子模块会更快。

默认情况下,一次获取一个子模块。
示例:

git fetch --recurse-submodules -j2

这个新功能的大部分是在commit c553c72(2015年12月16日)由Stefan Beller ( stefanbeller )

run-command:添加异步并行子处理器

这允许在stderr上并行运行外部命令和有序输出

如果我们并行运行外部命令,我们不能直接将输出通过管道传输到我们的stdout/err,因为它会混淆。所以每个进程的输出将通过管道流动,我们缓冲。一个子进程可以直接通过管道传输到out stdout/err,以向用户提供低延迟反馈。
请注意,在Git 2.24(2019年第4季度)之前,“git fetch --jobs=<n>”在获取子模块时允许<n>并行作业,但这不适用于从多个远程存储库获取的“git fetch --multiple”。
现在有了。
参见commit d54dea7(2019年10月5日),作者Johannes Schindelin ( dscho )
(由Junio C Hamano -- gitster --合并于commit d96e31e,2019年10月15日)

fetch:让--jobs=<n>也并行化--multiple

签署人:约翰内斯·申德林
到目前为止,--jobs=<n>只并行子模块提取/克隆,而不是--multiple提取,这是不直观的,因为该选项的名称没有特别说明任何关于子模块的内容。
让我们改变一下。

使用此修补程序,还可以并行化从多个远程设备获取数据

对于向后兼容性(以及为子模块和多远程提取可能需要不同并行化限制的用例做准备):

  • 配置设置X1 M17 N1 X仍然只控制X1 M18 N1 X的子模块部分,
  • 而新引入的设置fetch.parallel控制这两者(但是对于具有submodule.fetchJobs的子模块可以被覆盖)。

另请参阅Git 2.40(Q1 2023)和**git pull multiple remotes in parallel**,以了解该版本中修复的git fetch --jobs=0错误。

cidc1ykv

cidc1ykv2#

当我运行您的命令时,下载68 Mb需要338秒的墙时间。
下面的Python程序依赖于要安装的GNU parallel,

#! /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

在另一个目录中,反之亦然。

相关问题