12

私はGitXの作者です。GitX の機能の 1 つは、ここで見られるように、ブランチの視覚化です。

この視覚化は現在、git から発行されたコミットを正しい順序で読み取ることによって行われています。コミットごとに親がわかっているため、正しい方法でレーンを構築するのはかなり簡単です。

独自のコミット プールを使用し、コミットを自分で線形化することで、このプロセスをスピードアップしたいと考えています。これにより、既存のロードされたコミットを再利用でき、正しい順序でコミットを発行する必要がないため、git がコミットをより速く発行できるようになります。

ただし、これを達成するためにどのアルゴリズムを使用すればよいかわかりません。コミットのロードには長い時間がかかる可能性があるため (100,000 件のコミットで 5 秒以上、すべて表示される必要があります)、ビルドがインクリメンタルであることが重要です。

Gitk も同じように進んでおり、実装方法を示すパッチがここにありますが、私の TCL スキルは弱く、パッチは十分にコメントされておらず、理解するのが少し難しくなっています。

また、何十万ものコミットを処理する必要があるため、このアルゴリズムが効率的であることも望んでいます。また、表に表示する必要があるため、特定の行へのアクセスが高速であることが重要です。

これまでの入力、必要な出力、およびいくつかの観察事項について説明します。

入力:

  • コミット ID をコミット オブジェクトにマップするハッシュ テーブルの形式で、コミットの現在のプールがあります。このプールは完全である必要はありません (すべてのコミットが必要です)
  • 新しいコミットがロードされるたびに呼び出すことができるコールバックを使用して、git からの新しいコミットで別のスレッドをロードしています。コミットが行われる順序は保証されていませんが、ほとんどの場合、次のコミットは前のコミットの親になります。
  • commit オブジェクトには、独自のリビジョン ID とそのすべての親のリビジョン ID があります
  • リストする必要がある支部長のリストがあります。つまり、表示されるべき DAG の単一の「トップ」はありません。また、単一のグラフ ルートである必要もありません。

出力:

  • これらのコミットをトポロジー順に線形化する必要があります。つまり、親がリストされた後にコミットをリストすることはできません。
  • 上のスクリーンショットに見られる「分岐線」も必要です。それらのほとんどは子に依存しているため、これらはおそらく事前に計算する必要があります。

いくつかの注意事項:

  • コミットのリストを再配置する必要があります。たとえば、一方のヘッドを他方の先祖にするコミットが現れるまで、関連のないコミット (ブランチ ヘッド) が必要になる場合があります。
  • 複数のブランチ ヒントを表示する必要があります
  • データがまだロードされている間、少なくとも部分的なビューを利用できるように、このプロセスは増分的であることが重要です。これは、新しいデータを途中で挿入する必要があり、支線を再調整する必要があることを意味します。
4

4 に答える 4

6

標準のトポロジカル ソートは O(n) (OK, O(V+E)) です。つまり、メモリ内の 100 万件のコミットを一瞬でソートできるはずです。Tcl のようなインクリメンタル ハックは必要ありません。

ところで、私は毎日 GitX (OS X の Gitk よりもはるかに優れているように見えます) を使用していますが、問題はありません (おそらく、リポジトリにクレイジーなマージがないためです) :)

于 2009-04-03T02:46:01.893 に答える
3

わかりましたので、そのパッチ全体を読むのも同様に苦労していますが、私が把握したことからそれをつなぎ合わせることができるかどうか見てみましょう.

まず、gitk は一連のコミットをアークに凝縮することで物事を簡素化します。これには、それぞれが 1 つの親と 1 つの子のみを持つ一連のコミットが含まれます。他のことは別として、これを行うと、ソートのために考慮する必要があるノードの数が大幅に削減され、使用するアルゴリズムに役立ちます。おまけとして、関連するコミットはグループ化されます。

これにより、新しいコミットを読み取るときにアークを見つけるという点で、多少の複雑さが生じます。いくつかの状況があります:

  • 新しいコミットには、単一の親があるか、親がありません。(おそらく空の) 円弧を拡張します。ほとんどの場合、最新のアークを延長するだけです。興味深いサブケースがいくつかあります。
    • 親がすでに子を持っている場合、既存のアークが分割される可能性があります(つまり、その親が分岐点であることが判明しましたが、これは前もってわかりません)。
    • それは、2 つのアークをつなぐ「ミッシング リンク」である可能性があります。
    • このコミットには複数の子があることをすでに知っているかもしれません
  • 新しいコミットには複数の親があります (マージ コミット)。

複数の子または複数の親のコミットをアークに含めたい場合や、それらを別々にしておく方が理にかなっている場合があります。いずれにせよ、この弧のセットを段階的に構築することはそれほど難しくありません。

これらの円弧を取得したら、それらを線形化しようとする作業が残っています。あなたの場合、前述のウィキペディアのページで説明されている最初のアルゴリズムは、初期セット S.

その他の注意事項:

  • コミットの再配置は管理しやすいはずです。まず第一に、新しいマージ コミット、新たに発見された分岐点、または 2 つのアークを 1 つに結合することによって、2 つのアークを接続するときだけ気にする必要があります。任意のアークは、現在の行番号の範囲を簡単に維持できます (連続した行にアークを配置しても問題ないと仮定すると) ため、ツリーをたどって、すべての新しい先祖が後で表示されることを確認するのは非常に迅速です。
  • グラフの線を描くことについてはあまり詳しくありませんが、現在行っていることとあまり変わらないと思います。

とにかく、それが役立つことを願っています。少なくとも、考えるのは面白かったです。

于 2009-04-04T22:09:11.463 に答える