1. ホーム
  2. git

[解決済み] git はどのようにして類似ファイルを検出し、リネームを検出するのですか?

2022-12-10 18:42:19

質問

ウィキペディアの自動改名検出について教えてください。

簡単に言うと、リビジョン N のファイルが与えられたとき、リビジョン N-1 の同名のファイルが リビジョン N-1 の同名のファイルがそのデフォルトの先祖になります。しかし、リビジョン N-1 に リビジョン N-1 に同名のファイルがない場合、Git はリビジョン N-1 にのみ存在し、かつ リビジョン N-1 にのみ存在し 非常に似ている であるファイルを探します。

リネーム検出はどうやら類似ファイル検出に帰着するようです。そのアルゴリズムはどこかに文書化されていますか?どのような種類の変換が自動的に検出されるかを知ることは素晴らしいことです。

どのように解決するのですか?

Gitはファイル名ではなく、ファイルの内容を追跡します。そのため、内容を変更せずにファイル名を変更することは、gitにとって簡単に検出できます。(Gitは追跡しませんが 検出 を使用しています。 git mv または git rm そして git add は事実上同じです)。

ファイルがリポジトリに追加されるとき、ファイル名はツリーオブジェクトの中にあります。実際のファイルの中身はバイナリラージオブジェクト( ブロブ ) としてリポジトリに追加されます。Gitは、同じコンテンツを含む追加のファイルに対して別のblobを追加することはありません。実際、ハッシュの最初の2文字がディレクトリ名、残りがその中のファイル名となり、コンテンツはファイルシステムに格納されるため、Gitはそれを行うことができません。ですから、リネームを検出するのは、ハッシュを比較する問題なのです。

リネームされたファイルへの小さな変更を検出するために、Gitは特定のアルゴリズムと閾値制限を使用して、これがリネームであるかどうかを判断します。たとえば -M のフラグを見てみましょう。 git diff . また、次のような設定値もあります。 merge.renameLimit (マージ中にリネーム検出を行う際に考慮するファイル数) のような設定値もあります。

をどのように扱うかを理解するために、git は と同様の をどのように扱うのか (つまり、どのようなファイル変換をリネームとみなすのか) を理解するには、上で述べたように利用可能な設定オプションやフラグを調べます。方法については考慮する必要はありません。git が実際にどのようにこれらのタスクを達成しているかを理解するには、テキストの差分を見つけるためのアルゴリズムを見て、git のソースコードを読んでみてください。

アルゴリズムは diff、merge、log の目的のためにのみ適用されます -- git がどのように保存するかには影響しません。ファイルの内容におけるどんな小さな変更も、そのために新しいオブジェクトが追加されることを意味します。そのレベルでは、デルタやディフが発生することはありません。もちろん、後で、差分が packfiles に保存される場所にオブジェクトがパックされるかもしれませんが、それはリネームの検出とは関係ありません。