9

バージョン管理リポジトリの履歴を編集し、VCS 間でプロジェクトの履歴を移動するために使用できる reposurgeon というオープンソース ツールを作成し、維持しています。最近、Subversion のダンプ ファイルとリポジトリの読み取りを完全にサポートしました。しかし、reposurgeon がまだうまく機能していないことが 1 つあります。それは、git スタイルの DAG マージにコピーすることによって行われた Subversion ブランチのマージを変換することです。

この部分を正しく理解するには、git fast-import ストリームでのマージ コミットのセマンティクスを、私よりもはるかによく理解する必要があります。私の質問は、マージ コミット後に表示されるはずのコンテンツのバージョンについてです。

もちろん、マージコミットに添付されたファイルの変更により、その内容がそこに表示されます。私の質問は、コミットによって触れられていないパスに関するものです。

  1. パスが、マージの祖先の 1 つのコミット チェーンのみにコンテンツを持っている場合、コンテンツは表示されるはずだと思います。あれは正しいですか?

  2. パスにマージの祖先の複数のコミット チェーンのコンテンツがある場合、どのバージョンが表示されますか?

  3. ファイルがマージへのいくつかのパスに沿って削除された場合、マージ リビジョンでいつ削除されるかを予測するルールは何ですか?

4

1 に答える 1

8

私があなたの質問を理解していれば、コミットの内容をそこにストリーミングするときに fast-import でどのようなショートカットを使用できるか疑問に思っていることでしょう。

読んだこととマニュアルページからわかる限りgit/fast-import.c、高速インポートは、「from」コマンドで提供されたツリーからの新しいコミットのためにツリーを初期化します。「filemodify」と友達はその状態から始めて、最後にコミットされる新しいツリーを構築します。

「マージ」コマンドに遭遇した場合、fast-import コマンドはツリーをまったく変更しないように見えます。最初のもの以外の親からの変更を含めたい場合は、どのファイルを取り込むかを正確に指定する必要があります。マークまたはオブジェクトハッシュを使用して、「filemodify」の他のブランチファイルに名前を付けることができます。


編集: ああ、git モデルをさらに詳しく見てみましょう。

git では、コミットは、そのコミットの時点で立っていた、追跡されているディレクトリ階層の内容全体を表すツリーを指します。コミットには、親との違いに関する情報は含まれていません。理論的には、これらのツリーを比較することで、必要に応じて差分を再構築できるというものです。

マージ コミットは、2 つ以上の親を持つという事実によってのみ、非マージと区別されます。まだ 1 つのツリーがあり、マージを実行した結果のバージョンの内容が正確に記録されています。作成者がどのように親を結合してマージ バージョンにしたかについては、まだ何も記録されていません。git "porcelain" コマンドは likegit logおよびgit diffdo magic を使用して、何が起こったかの有用な説明を再構築します。

概念的には、新しいコミット オブジェクトを作成するには、そのコミットに含まれるファイル コンテンツへのパスの完全なマッピングを記述する必要があります。(ひどいものではなく、効率的でシンプルなものにするために、多くの賢さが必要です。)

このgit fast-importコマンドは、一般的なケースのショートカットを提供します。通常、エクスポート元の VCS は、このコミットが同じブランチの最新のコミットとの何らかの差分としてどのように形成されたかを知ることができます。その場合、diff を fast-import のストリーム形式に効果的にエンコードして、よりシンプルで高速なインポートを行うことができます。

ただし、これはツリー全体をゼロから再構築するための近道にすぎないことを覚えておく必要があります。

于 2012-11-05T02:19:24.700 に答える