当我第一次在具有大量子模块的项目上运行git submodule update --init
时,这通常需要花费很多时间,因为大多数子模块存储在慢速公共服务器上。
是否有可能异步初始化子模块?
答案 0 :(得分:5)
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
答案 1 :(得分:4)
从Git 2.8开始,你可以这样做
var routes = {
'first': '{{ route('first') }}',
'second': '{{ route('second') }}',
// ....
};
// Somewhere later in code
$http.get(routes.second).then(function(result) {
// do something
});
其中4是要并行下载的子模块数。
答案 2 :(得分:2)
2016年1月更新:
使用Git 2.8(2016年第一季度),您将能够使用git fetch --recurse-submodules -j2
并行(!)获取子模块。
请参阅“How to speed up / parallelize downloads of git submodules using git clone --recursive?”
2013年中期的原始答案
你可以尝试:
首先初始化所有子模块:
git submodule init
然后,foreach
syntax:
git submodule foreach git submodule update --recursive -- $path &
如果“&
”适用于所有行(而不仅仅是“git submodule update --recursive -- $path
”部分),那么您可以调用一个脚本来进行后台更新。
git submodule foreach git_submodule_update
答案 3 :(得分:1)
这也可以在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给出的单行更安全(因为那个只是保持产生进程而不对生成的进程数进行任何控制),仍然遵循相同的逻辑:read .gitmodules
,然后产生运行正确git命令的多个进程,但这里使用进程池(也可以设置最大进程数)。克隆存储库的路径需要作为参数传递。这在包含大约700个子模块的存储库中进行了广泛测试。
请注意,在子模块初始化的情况下,每个进程都会尝试写入.git/config
,并且可能会发生锁定问题:
错误:无法锁定配置文件.git / config:文件存在
无法为子模块路径'...'
注册网址
这可以通过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
有了这个,我设法在Travis构建期间运行700个子模块的初始化/更新,而不需要限制进程池的大小。我常常看到一些锁被锁定(最多约3个)。