一度に複数のリポジトリを処理する組み込みの方法はありません
しかし、あります。
Git 2.27(2020年第2四半期)はgit update-ref --stdin
、ユーザーがref updateトランザクションをより明示的に制御できるようにするために、いくつかの新しい動詞を学習した""で道を開きます。
これは、複数のリポジトリ間で2フェーズコミットスタイルのアトミック参照更新を実装するための要素として役立ちます。
Patrick Steinhardt()によるcommit e48cf33 、 commit 94fd491、commit de0e0d6、commit 804dba5、commit 5ae6c5a、commit a65b8ac(02 Apr 2020)、およびcommit bd021f3、commit faa35ee、commit edc3069(30 Mar 2020)を参照してください。(濱野純雄による合併---コミットd2ea03d、 2020年4月29日)pks-t
gitster
update-ref
:インタラクティブなトランザクション処理を実装する
サインオフ-作成者:Patrick Steinhardt
このgit-update-ref
コマンドは現在、「--stdin
」パラメーターを介してのみキューイングトランザクションを処理できますが、ユーザーがトランザクション自体をより明示的な方法で処理する方法はありません。
たとえば、複製されたシナリオでは、複数のリポジトリを生成するコーディネーターを想像することgit-update-ref
ができます。更新が可能であることに全員が同意した場合にのみ、コーディネーターはコミットを送信します。
このようなトランザクションセッションは、次のようになります。
> start
< start: ok
> update refs/heads/master $OLD $NEW
> prepare
< prepare: ok
# All nodes have returned "ok"
> commit
< commit: ok
また:
> start
< start: ok
> create refs/heads/master $OLD $NEW
> prepare
< fatal: cannot lock ref 'refs/heads/master': reference already exists
# On all other nodes:
> abort
< abort: ok
このようなトランザクションセッションを可能にするために、このコミットでは、の4つの新しいコマンドが導入されます。これは、「 」git-update-ref
を除いて、内部ですでに持っているコマンドと一致します。start
start
:新しいトランザクションを開始します
prepare
:トランザクションを準備します。つまり、すべての参照をロックし、それらの現在の値が期待される値と一致することを確認します
commit
:セッションを明示的にコミットします。つまり、参照を更新して、新しい期待される状態に一致させます。
abort
:セッションを中止し、すべての変更をロールバックします
設計上、git-update-ref
標準入力が閉じられるとすぐにコミットします。
非トランザクションの世界では問題ありませんが、トランザクションの世界では間違いなく予想外です。
このため、新しいトランザクションコマンドのいずれかが使用されるとすぐに、デフォルトは明示的な「commit
」なしで中止するように変更されます。キューイング更新とトランザクションを開始する
最初の""との間の競合を回避するために、明示的なトランザクションを開始するための""コマンドが追加されました。prepare
start
この新機能を実行するためのテストをいくつか追加します。
複数のリポジトリを一度に処理するための組み込みの方法は、Git 2.28(2020年第3四半期)と新しいフックで継続されます。
Patrick Steinhardt()によるcommit 6754159(2020年6月19日)を参照してください。(濱野純雄による合併---コミット33a22c1、2020年7月6日)pks-t
gitster
refs
:リファレンストランザクションフックを実装する
サインオフ-作成者:Patrick Steinhardt
参照の更新に使用される低レベルの参照トランザクションは、現在、ユーザーに対して完全に不透明です。
ほとんどのユースケースでは確かに望ましいですが、トランザクションにフックして、キューに入れられたすべての参照更新を監視し、準備されたトランザクションの中止またはコミットを監視したい場合もあります。
そのようなユースケースの1つは、特定のGitリポジトリのレプリカのセットを用意することです。この場合、すべてのリポジトリでGit操作を一度に実行し、すべてのリポジトリで同じ結果が得られると期待します。
このための投票メカニズムを実装するために使用できるGitコマンドの特定のサブセット用のフックがすでに存在しますが、他の多くの人は現在、これのためのメカニズムを持っていません。
上記のシナリオは、Gitの参照トランザクションメカニズムに直接到達する新しい「参照トランザクション」フックの動機です。
prepared
フックは、トランザクションが移動された現在の状態( " "、 " committed
"、または " ")をパラメーターとして受け取り、aborted
その標準入力を介して、キューに入れられたすべての参照更新を取得します。
終了コードは「コミット済み」および「中止」状態では無視されますが、ゼロ以外の終了コードが「準備済み」状態では、トランザクションが途中で中止されます。
上記のユースケースを考えると、投票メカニズムはこのフックを介して実装できるようになりました。呼び出されるとすぐに、すべてのstdinを取得し、それを使用して中央サービスに投票します。
リポジトリのすべてのレプリカが一致すると、フックはゼロで終了します。それ以外の場合は、ゼロ以外を返すことでトランザクションを中止します。
最も重要な利点は、これにより、参照を書き込むすべてのコマンドが一度にキャッチされ、単一のメカニズムを介して参照更新の強力な一貫性を実装できることです。
リポジトリに「reference-transaction」フックがインストールされていない場合の影響をテストするために、このコミットではgit-update-refsの2つの新しいパフォーマンステストを導入します。
空のリポジトリに対して実行すると、次の結果が生成されます。
Test origin/master HEAD
--------------------------------------------------------------------
1400.2: update-ref 2.70(2.10+0.71) 2.71(2.10+0.73) +0.4%
1400.3: update-ref --stdin 0.21(0.09+0.11) 0.21(0.07+0.14) +0.0%
パフォーマンステストp1400.2
では、ブランチが1000回作成、更新、削除されるため、平均git-update-refs
して3000回を超える呼び出しが実行されます。
p1400.3
代わりに、git-update-refs --stdin
3回呼び出して、それぞれ1000の作成、更新、削除をキューに入れます。
予想どおり、p1400.3
更新の各バッチについて、ネガティブフックルックアップのためのaccess(3P)への単一の呼び出しがあるため、一貫して目立った影響は示されません。
一方、の場合p1400.2
、このパッチセットによって引き起こされる影響を確認できます。ただし、パフォーマンステストを5回実行すると、それぞれがGIT_PERF_REPEAT_COUNT=10,
-1.5%から+ 1.1%の範囲のオーバーヘッドで実行されました。これらの一貫性のないパフォーマンスの数値は、3000プロセスを生成するオーバーヘッドによって説明できます。これは、フックパスをアセンブルし、access(3P)を1回実行して、そこにあるかどうかを確認するオーバーヘッドが、オペレーティングシステムのオーバーヘッドよりもほとんど大きいことを示しています。
Git 2.29(2020年第4四半期)では、効果のない最適化を削除することで、フックが簡素化されています。
Patrick Steinhardt()によるcommit 0a0fbbe(2020年8月25日)を参照してください。( Junio C Hamanoによってマージされました---コミット6ddd76f 、2020年8月31日)pks-t
gitster
refs
reference-transaction
:フックのルックアップキャッシュを削除します
サインオフ-作成者:Patrick Steinhardt
フックを追加する際reference-transaction
、新しいフックをまったく使用しないセットアップにパフォーマンスが与える可能性があるという懸念がありました。
結局のところ、aが準備、コミット、または中止されるたびに実行さreftx
れ、セッションごとに作成された参照トランザクションの数に比例してスケーリングします。また、更新する参照ごとに新しいトランザクションを作成する(man)
のようなコードパスがあるため、これは非常に多くの呼び出しにつながる可能性があります。git push
find_hook()
この懸念に対処するために、ネガティブフックルックアップを繰り返し実行しないようにキャッシュが追加されました。
このキャッシュがリグレッションを引き起こしたことが判明しました。これはe5256c82e5を介して修正されました( " refs
:参照トランザクションフックを使用したインターリーブフック呼び出しの修正"、2020-08-07、Git v2.29.0 --マージはバッチ#8にリストされています)。
修正について話し合う過程で、ネガティブルックアップの場合でもキャッシュは実際には役に立たないことに気づきました。
ベンチマークに追加されたパフォーマンステストでは、1%の範囲でわずかな改善が見られましたが、これは実際にはキャッシュがあることを保証するものではありません。
さらに、それもかなり不安定です。たとえば、2回続けて実行すると、次の結果が得られます。
Test master pks-reftx-hook-remove-cache
--------------------------------------------------------------------------
1400.2: update-ref 2.79(2.16+0.74) 2.73(2.12+0.71) -2.2%
1400.3: update-ref --stdin 0.22(0.08+0.14) 0.21(0.08+0.12) -4.5%
Test master pks-reftx-hook-remove-cache
--------------------------------------------------------------------------
1400.2: update-ref 2.70(2.09+0.72) 2.74(2.13+0.71) +1.5%
1400.3: update-ref --stdin 0.21(0.10+0.10) 0.21(0.08+0.13) +0.0%
これらのベンチマークに特に欠けている1つのケースは、フックを数百回検索する単一の実行可能ファイルです。これは、ネガティブキャッシュが追加されたケースとまったく同じです。
p1400.2
トランザクションごとに新しいupdate-refを生成し、p1400.3
すべての参照更新に対して単一の参照トランザクションのみを持ちます。
したがって、このコミットは3番目のベンチマークを追加します。これは、1000の参照の非アトミックプッシュを実行します。これにより、参照ごとに新しい参照トランザクションが作成されます。ただし、この場合でも、ネガティブキャッシュによってパフォーマンスが一貫して向上するわけではありません。
Test master pks-reftx-hook-remove-cache
--------------------------------------------------------------------------
1400.4: nonatomic push 6.63(6.50+0.13) 6.81(6.67+0.14) +2.7%
1400.4: nonatomic push 6.35(6.21+0.14) 6.39(6.23+0.16) +0.6%
1400.4: nonatomic push 6.43(6.31+0.13) 6.42(6.28+0.15) -0.2%
それでは、コードを単純化するために、キャッシュを完全に削除しましょう。
Git 2.30(Q1 2021)では、「(man)」は1回のセッションで複数のトランザクションを実行することを学習します。git update-ref --stdin
Patrick Steinhardt()によるcommit 8c4417f、commit 2102043、commit 262a4d2、commit c0e1726(2020年11月13日)を参照してください。( Junio C Hamanoによってマージされました---コミット1bc550e、2020年12月8日)pks-t
gitster
サインオフ-作成者:Patrick Steinhardt
レビュー者:Jeff King
git-update-refは最近、e48cf33b61でトランザクションのインタラクティブな制御を可能にするコマンドを開発しました( " update-ref
:インタラクティブなトランザクション処理を実装する"、2020-04-02、Git v2.27.0-rc0 --マージはバッチ#5にリストされています)。 1つのセッションで複数のトランザクションを作成することはまだできません。そのためには、現在でも実行可能ファイルを複数回呼び出す必要があります。
このコミットは、現在のトランザクションがすでにコミットまたは中止されている場合に「start」コマンドで新しいトランザクションを作成できるようにすることで、この欠点に対処します。
git update-ref
現在、そのマニュアルページに含まれています:
明示的なコミット。このコマンドは、現在のトランザクションがすでにコミットまたは中止されている場合に、新しい空のトランザクションを作成する場合があります。
Git 2.34(Q4 2021)より前は、 " git update-ref
" (man) --stdin
は必要に応じて出力をフラッシュできなかったため、会話がデッドロックに陥る可能性がありました。
これは修正されており、前述のパスの結果でした。
Patrick Steinhardt()によるcommit efa3d64(2021年9月3日)を参照してください。Jeff King()によるcommit 7c12007(2021年9月15日)
を参照してください。( Junio C Hamanoによってマージされました---コミット06a0eea、2021年9月23日)pks-t
peff
gitster
サインオフ-作成者:Patrick Steinhardt
フラグを指定してgit-update-ref(1)を実行する--stdin
と、ユーザーは更新をキューに入れることができます。e48cf33( " update-ref
:インタラクティブなトランザクション処理を実装する"、2020-04-02、Gitv2.27.0- rc0--マージバッチ#5)、一連のトランザクション動詞を介してトランザクションの状態をインタラクティブに駆動します。
ただし、この対話性は多少壊れています。呼び出し元はこれらの動詞を使用してトランザクションの状態を駆動できますが、動詞が処理されたことを確認するステータスメッセージはフラッシュされません。
したがって、発信者は、確認応答を待つためにぶら下がったままになる可能性があります。
ステータスアップデートを書き込んだ後、stdoutをフラッシュしてバグを修正します。