SYNOPSIS

git diff *

DESCRIPTION

diffコマンド gitdiff-indexgit diff-filesgit diff-tree は、 diff 出力を表示する前に、従来とは異なる方法で検出した差異を操作するように指示できます。この操作を総称して「diffcore変換」(diffcore transformation)と呼びます。この短いノートでは、それらが何であるか、およびそれらを使用して、従来の種類よりも理解しやすい diff 出力を生成する方法について説明します。

The chain of operation

git diff-{asterisk} ファミリの仕事は、まずは2つのファイルセットを比較することです:

  • git diff-index は、 (--cached フラグが使用されていない場合)ツリーオブジェクトと作業ディレクトリの内容を比較するか、または(` --cached` フラグが使用されている場合)ツリーオブジェクトとインデックスファイルの内容を比較します。

  • git diff-files は、インデックスファイルと作業ディレクトリの内容を比較します。

  • git diff-tree は、2つのツリーオブジェクトの内容を比較します。

これらすべての場合において、コマンド自体は、最初にオプションで、コマンドラインで指定されたパススペックによって2つのファイルの組を限定し、結果として得られる2つのファイルの組の対応するパスを比較します。

パススペックは、diffが動作するワールドを制限するために使用されます。これらは、指定されたパス名の組の外側にあるファイルペア(filepairs)を削除します。例えば。ファイルペアの入力組が含まれている場合:

:100644 100644 bcd1234... 0123456... M junkfile

しかし、コマンドの呼び出しが git diff-files myfile の場合、 myfile のみが考慮されているため、junkfileエントリがリストから削除されます。

比較の結果は、これらのコマンドから、 `-p` オプションが使用されていない場合に出力されるものと同様の形式で、内部的に「diffcore」と呼ばれるものに渡されます。例えば

in-place edit  :100644 100644 bcd1234... 0123456... M file0
create         :000000 100644 0000000... 1234567... A file4
delete         :100644 000000 1234567... 0000000... D file5
unmerged       :000000 000000 0000000... 0000000... U file6

diffcoreメカニズムには、そのような比較結果のリストが提供され(それぞれが「ファイルペア」(filepair)と呼ばれますが、この時点ではそれぞれ1つのファイルについて話します)、そのようなリストを別のリストに変換します。現在、そのような変換(transformations)は5つあります:

  • diffcore-break

  • diffcore-rename

  • diffcore-merge-broken

  • diffcore-pickaxe

  • diffcore-order

  • diffcore-rotate

これらは順番に適用されます。 git diff-{asterisk} コマンド群の探索のファイルペアのセットは、diffcore-breakへの入力として使用されます。diffcore-breakからの出力は、次の変換への入力として使用されます。そして、最終結果が出力ルーチンに渡され、diff-raw形式(マニュアルの git diff-{asterisk} コマンド の「Output format」セクションを参照)またはdiff-patch形式のいずれかが生成されます。

diffcore-break: 完全な書き換えを分割するため

操作チェーンの2番目の変換(transformation)はdiffcore-breakで、 git diff-{asterisk} コマンド群の -B オプションによって制御されます。これは、「完全な書き換え」を表すファイルペアを検出し、そして、そのようなファイルペアを削除と作成を表す2つのファイルペアに分割するために使用されます。例えば、入力に以下のファイルペアが含まれている場合:

:100644 100644 bcd1234... 0123456... M file0

そして、ファイル "file0" が完全に書き換えられたことを検出すると、以下のように変更されます:

:100644 000000 bcd1234... 0000000... D file0
:000000 100644 0000000... 0123456... A file0

ファイルペアを切断する(break)目的で、diffcore-breakは、変更前後のファイルの内容(つまり、上記の例では、SHA-1コンテンツIDとして bcd1234...0123456... を持つコンテンツ)の間の変更の程度を調べます。元のコンテンツの削除と新しい素材の挿入の量が合計され、「ブレークスコア」(break score)を超えると、ファイルペアが2つに分割されます。ブレークスコアのデフォルトは、元のサイズと結果の小さい方のサイズの50%であり(つまり、編集によってファイルが縮小される場合は、結果のサイズが使用されます。編集によってファイルが長くなる場合は、元のサイズが使用されます)、 -B オプションの後に数字を付けることでカスタマイズできます(たとえば、 -B75 で75%にするように指示します)。

diffcore-rename: 名前変更とコピーを検出するため

この変換(transformation)は、名前変更とコピーを検出するために使用され、 git diff-{asterisk} コマンド群の -M オプション(名前変更検出用)と -C オプション(コピーも検出するため)によって制御されます。入力にこれらのファイルペアが含まれている場合:

:100644 000000 0123456... 0000000... D fileX
:000000 100644 0000000... 0123456... A file0

ここで、削除されたファイルfileXの内容は、作成されたファイルfile0の内容と十分に類似しているため、名前変更検出はこれらのファイルペアをマージして以下を作成します:

:100644 100644 0123456... 0123456... R100 fileX file0

-C オプションを使用すると、変更されたファイルと削除されたファイル( --find-copies-harder オプションが使用されている場合は、変更されていないファイルも)の元の内容が、名前変更/コピー 操作のソースファイルの候補と見なされます。入力がこれらのファイルペアのようなものである場合、変更されたファイルfileYと新しく作成されたファイルfile0について以下のようになります:

:100644 100644 0123456... 1234567... M fileY
:000000 100644 0000000... bcd3456... A file0

fileYの元の内容とfile0の結果の内容が比較され、それらが十分に類似している場合は、以下のように変更されます:

:100644 100644 0123456... 1234567... M fileY
:100644 100644 0123456... bcd3456... C100 fileY file0

名前の変更とコピーの検出の両方で、diffcore-breakで使用されるのと同じ「変更の範囲」(extent of changes)アルゴリズムを使用して、2つのファイルが「十分に類似」しているかどうかを判断し、デフォルトの50%とは異なる類似スコアを使用するようにカスタマイズできます。 -M または -C オプションの後に番号を付けます(たとえば、 -M8 で 8/10 = 80% にするように指示します)。

注意: 名前変更検出がオンで、コピーとブレークの両方の検出がオフの場合、名前変更検出は、ファイル名を同じに保ちながらファイルがディレクトリ間で移動されるかどうかを最初にチェックする予備ステップを追加することに注意してください。 別のディレクトリから削除された同じ名前のファイルと内容が十分に類似しているファイルがディレクトリに追加されている場合、それらを名前変更としてマークし、後の2次ステップ(一致しないすべてのファイルをペアごとに比較して、コンテンツの類似性が最も高いことによって決定される「最良の」一致を見つけるステップ)から除外します。したがって、たとえば、削除された docs/ext.txt と追加された docs/config/ext.txt が十分に類似している場合、それらは名前変更としてマークされ、削除された docs/ext.txt にさらに類似している可能性のある、追加された docs/ext.md が後のステップで名前変更先と見なされないようにします。 このため、予備の「同じファイル名に一致」ステップでは、少し高いしきい値を使用してファイルペアを名前変更としてマークし、他の候補をより適切に一致させることを検討しなくなります。 この予備ステップでは、ファイルごとに最大で1つの比較が行われます。したがって、正確な名前変更が検出された後、ディレクトリ階層全体にext.txtファイルがいくつか残っている場合は、これらのファイルのこの準備手順をスキップできます。

注意: -C オプションを --find-copies-harder オプションとともに使用すると、 git diff-{asterisk} コマンド群は、変更されていないファイルペアと変更されたファイルペアをdiffcoreメカニズムに送ります。これにより、コピー検出器は、ファイルの速度を低下させる代わりに、変更されていないファイルをコピーソース候補と見なすことができます。 --find-copies-harder がないと、 git diff-{asterisk} コマンド群は、コピーされたファイルがたまたま同じチェンジセットで変更された場合にのみコピーを検出できます。

diffcore-merge-broken: 完全な書き換えを元に戻すため

この変換は、diffcore-breakによって分割したファイルペアをマージするために使用され、 diffcore-rename によって rename/copy に変換されず、単一の変更に戻されます。これは、diffcore-breakが使用されている場合は常に実行されます。

分割したファイルペアをマージする目的で、 diffcore-break および diffcore-rename で使用されるものとは異なる「変更の範囲」の計算を使用します。オリジナルからの削除のみをカウントし、挿入はカウントしません。100行のドキュメントから10行だけを削除した場合、新しい1000行のドキュメントを作成するために910行を追加しても、完全な書き換えは行われたとは見なしません。 diffcore-break は、 diffcore-renameがそのようなファイルペアを 名前変更/コピー 検出の候補と見なすのを助けるためにそのような場合のを分割しますが、その方法で分割したファイルペアが他のファイルペアと一致して 名前変更/コピー を作成しなかった場合、この変換でそれらをマージして「元の変更」に戻します 。

「変更の範囲」パラメータは、 -B に2番目の数値を指定することで、デフォルトの80%から微調整できます(つまり、元のマテリアルの80%以上が削除されない限り、分割されたペアは1つの変更にマージされます)。以下のように指定できます:

  • -B50/60 (diffcore-breakに50%の「ブレークスコア」を与え、diffcore-merge-brokenに60%を与えます)。

  • -B/60 (上記と同じです。diffcore-breakのデフォルトは50%であるため)。

注意:以前の実装では、個別の作成パッチと削除パッチとして分割したペアが残っていたことに注意してください。これは不必要なハックであり、最新の実装では常にすべての分割されたペアが変更にマージされます。ただし、結果のパッチ出力は、 - で始まる古いバージョンのコンテンツ全体を表示することにより、このような完全な書き換えの場合に簡単に確認できるように、異なる形式になっています。その後に、接頭辞 + が付いた新しいバージョンのコンテンツ全体が続きます。

diffcore-pickaxe: 指定の文字列(string)の追加/削除の検知のため

この変換により、ファイルペアの組が、特定の方法でプリイメージとポストイメージの間で指した文字列を変更するものに制限されます。 -S<テキストのブロック> および -G<正規表現> オプションは、これらの文字列を検索するさまざまな方法を指定するために使用されます。

-S<テキストブロック> は、指定されたテキストのブロックの出現回数がプリイメージとポストイメージで異なるファイルペアを検出します。定義上、ファイル内の移動は検出されません。また、チェンジセットが対象の文字列に影響を与えずにファイルを大規模に移動すると、通常どおりdiffcore-renameが開始され、-S はファイルペアを省略します(その文字列の出現回数は、名前変更で検出されたファイルペアで変更されなかったため)。 --pickaxe-regex と一緒に使用する場合、<テキストブロック>は、リテラル文字列ではなく、マッチする拡張POSIX正規表現として扱います。

-G<正規表現> (grep文法)は、指定された正規表現にマッチする行が追加または削除されたテキスト差分を持つファイルペアを検出します。これは、ノイズであるファイル内の移動(またはrename-detectionが同じファイルと見なすもの)を検出することを意味します。実装はdiffを2回実行してgrepsしますが、これは非常にコストがかかる可能性があります。高速化のため、textconvフィルタがないバイナリファイルは無視されます。

-S または -G--pickaxe-all なしで使用すると、それぞれの基準に一致するファイルペアのみが出力に保持されます。 --pickaxe-all が使用されている場合、1つのファイルペアでもチェンジセット内のそれぞれの基準に一致すると、チェンジセット全体が保持されます。この振る舞いは、チェンジセット全体のコンテキストでの変更のレビューを容易にするために設計されています。

diffcore-order: ファイル名に基づいて出力をソートするため

これは、ユーザー(またはプロジェクト)の好みに応じてファイルペアを並べ替えるために使用され、 git diff-{asterisk} コマンド群の -O オプションによって制御されます。

これは、各行がシェルグロブパターンであるテキストファイルを取ります。ファイルの前の行のグロブパターンに一致するファイルペアは、後の行に一致するファイルペアの前に出力され、どのグロブパターンにも一致しないファイルペアは最後に出力されます。

例として、コアGitの一般的な orderfile おそらく以下のようになります:

README
Makefile
Documentation
*.h
*.c
t

diffcore-rotate: 出力開始パス(path)を変更するため

この変換は1つのパス名を取り、ファイルペアのセットをローテーションして、指定されたパス名のファイルペアが最初に来るようにします。オプションで、その前にあるパスを破棄します。これは、 --skip-to および --rotate-to オプションを実装するために使用されます。指定されたパス名がファイルペアのセットにない場合はエラーになりますが、 git log ` ファミリーのコマンドで使用するとエラーになることはありません。 `git log コマンドで表示されるすべてのコミットによって特定のパスが変更されることを期待するのは不合理だからです。このため、 git log と一緒に使用すると、指定されたパス名と同じように並べ替えられるファイルペア、または最初に並べ替えられるファイルペアが出力の開始場所になります。

この変換をdiffcore-orderと組み合わせて使用すると、diffcore-orderが有効な場合、この変換への入力がソートされない可能性があるため、予期しない結果が生成されます。

SEE ALSO

GIT

Part of the git(1) suite