当我在有很多子模块的项目上第一次运行git submodule update --init
时,这通常需要很长时间,因为大多数子模块都存储在慢公共服务器上。Git submodule init async
是否有可能异步初始化子模块?
当我在有很多子模块的项目上第一次运行git submodule update --init
时,这通常需要很长时间,因为大多数子模块都存储在慢公共服务器上。Git submodule init async
是否有可能异步初始化子模块?
更新2016年1月:
使用Git 2.8(Q1 2016),您将能够为平行git fetch --recurse-submodules -j2
取子模块(!)。
请参阅 “How to speed up/parallelize downloads of git submodules using git clone --recursive?”
原来的答复2013年中期
你可以尝试:
初始化第一所有子模块:
git的子模块初始化
然后,foreach
syntax:
git submodule foreach git submodule update --recursive -- $path &
如果“&
”适用于所有线路(而不是只是“git submodule update --recursive -- $path
”部分),那么你可以调用一个脚本这将使更新在后台。
git submodule foreach git_submodule_update
OP表示“第一次”,这意味着子模块尚未初始化以运行“foreach”命令。对? –
您可能还想添加递归标志 –
@ hus787然后尝试'git submodule init first'(这不是一个昂贵的操作),然后是更新的''foreach''子模块。 – VonC
的Linux:
cat .gitmodules | grep -Po '".*"' | sed 's/.\(.\+\).$/\1/' | while sleep 0.1 && read line; do git submodule update --init $line & done
的Mac:
cat .gitmodules | grep -o '".*"' | cut -d '"' -f 2 | while sleep 0.1 && read line; do git submodule update --init $line & done
这也可以在Python完成。在Python 3(因为我们是在2015年......),我们可以用这样的:
#!/usr/bin/env python3
import os
import re
import subprocess
import sys
from functools import partial
from multiprocessing import Pool
def list_submodules(path):
gitmodules = open(os.path.join(path, ".gitmodules"), 'r')
matches = re.findall("path = ([\w\-_\/]+)", gitmodules.read())
gitmodules.close()
return matches
def update_submodule(name, path):
cmd = ["git", "-C", path, "submodule", "update", "--init", name]
return subprocess.call(cmd, shell=False)
if __name__ == '__main__':
if len(sys.argv) != 2:
sys.exit(2)
root_path = sys.argv[1]
p = Pool()
p.map(partial(update_submodule, path=root_path), list_submodules(root_path))
这可能比@Karmazzin给出的一行代码更安全(因为一个只是不断产卵过程但是它遵循相同的逻辑:读取.gitmodules
,然后产生运行适当的git命令的多个进程,但是这里使用进程池(最大进程数量也可以设置)。克隆存储库的路径需要作为参数传递。这在一个有大约700个子模块的存储库上进行了广泛的测试。
注意,在一个子模块的初始化的情况下,每个进程将尝试写入.git/config
,和锁定问题可能会发生:
error: could not lock config file .git/config: File exists
Failed to register url for submodule path '...'
这可以用subprocess.check_output
捕获和try/except subprocess.CalledProcessError
块,这是更清洁比添加到@ Karmazzin方法的睡眠。更新的方法可以是这样的:
def update_submodule(name, path):
cmd = ["git", "-C", path, "submodule", "update", "--init", name]
while True:
try:
subprocess.check_output(cmd, stderr=subprocess.PIPE, shell=False)
return
except subprocess.CalledProcessError as e:
if b"could not lock config file .git/config: File exists" in e.stderr:
continue
else:
raise e
有了这个,我设法在一个特拉维斯建立,而不需要限制进程池的大小运行的700子模块初始化/更新。我经常会看到几个锁(这是最多〜3个)。
正如吉特2.8,你可以这样
git submodule update --init --jobs 4
其中4是并行下载子模块的数量。
你是什么意思与异步?会这样做:'git submodule update --init&'? – rodrigo
我的意思是每个子模块在不同的过程中初始化的一种方式。 – Leksat
也就是说,平行而不是顺序? –