13

git submodule update --init多くのサブモジュールを含むプロジェクトで初めて実行する場合、ほとんどのサブモジュールが低速のパブリック サーバーに格納されているため、通常、これには多くの時間がかかります。

サブモジュールを非同期で初期化する可能性はありますか?

4

4 に答える 4

5

Linux:

cat .gitmodules | grep -Po '".*"' | sed 's/.\(.\+\).$/\1/' | while sleep 0.1 && read line; do git submodule update --init $line & done

マック:

cat .gitmodules | grep -o '".*"' | cut -d '"' -f 2 | while sleep 0.1 && read line; do git submodule update --init $line & done
于 2013-06-26T14:08:31.463 に答える
4

Git 2.8以降、これを行うことができます:

git submodule update --init --jobs 4

ここで、4 は並行してダウンロードするサブモジュールの数です。

于 2016-06-20T19:43:57.930 に答える
2

2016 年 1 月の更新:

Git 2.8 (2016 年第 1 四半期) では、サブモジュールを並列 (!) でフェッチできるようになりますgit fetch --recurse-submodules -j2「 git clone --recursive を使用して git サブモジュールのダウンロードを高速化/並列化する方法は?」を
参照してください。


2013年半ばの元の回答

あなたは試すことができます:

  • 最初にすべてのサブモジュールを初期化するには:

    git サブモジュールの初期化

次に、foreach構文

git submodule foreach git submodule update --recursive -- $path &

' &' が (' ' 部分だけでなく) すべての行に適用される場合git submodule update --recursive -- $path、バックグラウンドで更新を行うスクリプトを呼び出すことができます。

git submodule foreach git_submodule_update
于 2013-06-26T13:14:37.973 に答える
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: ファイルが存在します

サブモジュール パス '...' の URL を登録できませんでした

これは、@ Karmazzin のメソッドに追加されたスリープよりもクリーンなブロックでsubprocess.check_outputキャッチできます。try/except subprocess.CalledProcessError更新されたメソッドは次のようになります。

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 のサブモジュールの init/update を実行することができました。いくつかのロックがそのように引っかかっているのをよく見かけます (最大 3 つまで)。

于 2015-09-30T15:15:41.940 に答える