回答:
gitの履歴からの高度な差分の例を見てみましょう(git.gitリポジトリのコミット1088261fで):
diff --git a/builtin-http-fetch.c b/http-fetch.c
similarity index 95%
rename from builtin-http-fetch.c
rename to http-fetch.c
index f3e63d7..e8f44ba 100644
--- a/builtin-http-fetch.c
+++ b/http-fetch.c
@@ -1,8 +1,9 @@
#include "cache.h"
#include "walker.h"
-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
+int main(int argc, const char **argv)
{
+ const char *prefix;
struct walker *walker;
int commits_on_stdin = 0;
int commits;
@@ -18,6 +19,8 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix)
int get_verbosely = 0;
int get_recover = 0;
+ prefix = setup_git_directory();
+
git_config(git_default_config, NULL);
while (arg < argc && argv[arg][0] == '-') {
このパッチを行ごとに分析してみましょう。
最初の行
diff --git a / builtin-http-fetch.cb / http-fetch.cフォームの「git diff」ヘッダー
diff --git a/file1 b/file2
です。a/
およびb/
名前変更/コピーが(私たちの場合のように)関与しなければ、ファイル名は同じです。これ--git
は、diffが「git」diff形式であることを意味します。次は、1つ以上の拡張ヘッダー行です。最初の3つ
類似性インデックス95% builtin-http-fetch.cから名前を変更 http-fetch.cに名前変更ファイルの名前がからに変更さ
builtin-http-fetch.c
れhttp-fetch.c
、これら2つのファイルは95%同一である(この名前の変更を検出するために使用された)ことを伝えてください。インデックスf3e63d7..e8f44ba 100644与えられたファイルのモード(
100644
symlinkではなく、通常のファイルであり、実行許可ビットがないことを意味します)、およびプリイメージ(与えられた変更前のファイルのバージョン)とポストイメージ(変更後のファイルのバージョン)。この行はgit am --3way
、パッチを適用できない場合に3者間マージを試行するために使用されます。次は2行の統一されたdiffヘッダーです
--- a / builtin-http-fetch.c +++ b / http-fetch.c
diff -U
結果と比較すると、ソース(プリイメージ)と宛先(ポストイメージ)のファイル名の後に、from-file-modification-timeもto-file-modification-timeもありません。ファイルが作成された場合、ソースは/dev/null
です。ファイルが削除された場合、ターゲットは/dev/null
です。構成変数をtrueにdiff.mnemonicPrefix
するa/
とb/
、この2行のヘッダーのとの代わりc/
にi/
、比較対象にそれぞれ、、w/
およびo/
プレフィックスを付けることができます。git-config(1)を参照してください次に、1つまたは複数の違いがあります。各ハンクは、ファイルが異なる1つの領域を示しています。統一フォーマットのハンクは次のような行で始まります
@@ -1,8 +1,9 @@または
@@ -18,6 +19,8 @@ int cmd_http_fetch(int argc、const char ** argv、...フォーマットです
@@ from-file-range to-file-range @@ [header]
。from-file-rangeの形式は-<start line>,<number of lines>
で、to-file-rangeは+<start line>,<number of lines>
です。start-lineとnumber-of-linesはどちらも、それぞれプリイメージとポストイメージのハンクの位置と長さを表します。行数が示されていない場合は、0であることを意味します。
オプションのヘッダーは、Cファイル(-p
GNU diffのオプションのような)の場合、各変更が発生するC関数、または他のタイプのファイルの同等のファイル(ある場合)を示します。
次に、ファイルが異なる場所について説明します。両方のファイルに共通の行は、空白文字で始まります。2つのファイル間で実際に異なる行の左側の印刷列には、以下の標識文字の1つがあります。
たとえば、最初のチャンク
#include "cache.h"
#include "walker.h"
-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
+int main(int argc, const char **argv)
{
+ const char *prefix;
struct walker *walker;
int commits_on_stdin = 0;
int commits;
cmd_http_fetch
がに置き換えられmain
、そのconst char *prefix;
行が追加されたことを意味します。
つまり、変更前の「builtin-http-fetch.c」ファイルの適切なフラグメントは次のようになっていました。
#include "cache.h"
#include "walker.h"
int cmd_http_fetch(int argc, const char **argv, const char *prefix)
{
struct walker *walker;
int commits_on_stdin = 0;
int commits;
変更後、この「http-fetch.c」ファイルのこのフラグメントは、代わりに次のようになります。
#include "cache.h"
#include "walker.h"
int main(int argc, const char **argv)
{
const char *prefix;
struct walker *walker;
int commits_on_stdin = 0;
int commits;
あるかもしれません
\ファイルの終わりに改行なし行が存在します(diffの例にはありません)。
ドナル・フェローと述べ、それはあなたが変更したものを知っている実際の例、上の差分を読んで練習するのが最善です。
参照:
git blame -C -C
。それはGit設計の決定です。git diff形式は、類似性(または非類似性)インデックスをユーザーに表示するだけです。
[header]
は、ハンクの前にある関数の開始と最も近い先行です。ほとんどの場合、この行には、diffのチャンクがある関数の名前が含まれています。これは、diff
gitattributeをdiffドライバーに設定し、xfuncname
構成変数を含むdiffドライバーで構成できます。
@@ -1,2 +3,4 @@
差分の一部
この部分を理解するのに少し時間がかかったので、最小限の例を作成しました。
形式は基本的にはdiff -u
統一された差分と同じです。
例えば:
diff -u <(seq 16) <(seq 16 | grep -Ev '^(2|3|14|15)$')
ここでは、2、3、14、15行目を削除しました。出力:
@@ -1,6 +1,4 @@
1
-2
-3
4
5
6
@@ -11,6 +9,4 @@
11
12
13
-14
-15
16
@@ -1,6 +1,4 @@
手段:
-1,6
これは、最初のファイルのこの部分が1行目から始まり、合計6行を示していることを意味します。したがって、1行目から6行目までを示しています。
1
2
3
4
5
6
-
通常はとして呼び出すため、「古い」を意味しdiff -u old new
ます。
+1,4
2番目のファイルのこの部分は1行目から始まり、合計4行を示します。したがって、1行目から4行目までを示しています。
+
「新しい」を意味します。
2行が削除されたため、6行ではなく4行しかありません!新しいハンクは次のとおりです。
1
4
5
6
@@ -11,6 +9,4 @@
2番目のハンクも同様です。
古いファイルには、古いファイルの11行目から始まる6行があります。
11
12
13
14
15
16
新しいファイルには、新しいファイルの9行目から始まる4行があります。
11
12
13
16
行11
は新しいファイルの9行目であることに注意してください。前のハンクで2行と2行がすでに削除されているためです。
ハンクヘッダー
gitのバージョンと設定に応じて、行の横にコード行を取得することもできます@@
(例func1() {
:in :)。
@@ -4,7 +4,6 @@ func1() {
これ-p
はplain のフラグで取得することもできdiff
ます。
例:古いファイル:
func1() {
1;
2;
3;
4;
5;
6;
7;
8;
9;
}
lineを削除する6
と、diffに次のように表示されます。
@@ -4,7 +4,6 @@ func1() {
3;
4;
5;
- 6;
7;
8;
9;
これは正しい行ではないことに注意してくださいfunc1
:行をスキップ1
しました2
。
この素晴らしい機能は、多くの場合、各ハンクがどの関数またはクラスに属しているかを正確に伝えます。これは、diffを解釈するのに非常に役立ちます。
ヘッダーを選択するアルゴリズムが正確にどのように機能するかについては、「git diff hunkヘッダーの抜粋はどこから来るのですか?」で説明されています。
@@ -1,6 +1,4 @@
plsは読んでいない-1
として、minus one
または+1
としてplus one
の代わりとしてこれを読んでline 1 to 6
、古い(最初の)ファイルインチ ここで- implies "old"
はマイナスではないことに注意してください 。ところで、説明してくれてありがとう... haash。
+1,4
この部分は2番目のファイルの1行目から4行目までに相当すると述べています」。これは、+1,4
非偶発的なコンテキスト行を参照する可能性があるためです。むしろ、どのような「+1,4
」実際に意味するということである「がある4
ファイルの『バージョン』の行(つまり、コンテキスト行が)」。の意味を理解することが重要である+
、-
と<whitespace>
それが兄貴の解釈に適用されるように、これらの行の先頭に。より視覚的な例:youtube.com/watch
これが簡単な例です。
diff --git a/file b/file
index 10ff2df..84d4fa2 100644
--- a/file
+++ b/file
@@ -1,5 +1,5 @@
line1
line2
-this line will be deleted
line4
line5
+this line is added
--git
コマンドではありません。これは、それがgitバージョンのdiff(UNIXではない)であることを意味しますa/ b/
ディレクトリであり、実際のものではありません。同じファイルを扱う場合に便利です(私の場合、a /はインデックスにあり、b /は作業ディレクトリにあります)10ff2df..84d4fa2
これら2つのファイルのblob IDです100644
これは「モードビット」であり、これが通常のファイルであることを示します(実行可能ファイルではなく、シンボリックリンクではありません)。--- a/file +++ b/file
マイナス記号は、a /バージョンの行を示しますが、b /バージョンにはありません。プラス記号は、a /にはないがb /にはある行を示します(私の場合---は削除された行を意味し、+++はb /に追加された行を意味し、これは作業ディレクトリ内のファイルです)@@ -1,5 +1,5 @@
これを理解するには、大きなファイルを操作する方がよいでしょう。異なる場所に2つの変更がある場合、次のような2つのエントリが表示され@@ -1,5 +1,5 @@
ます。ファイルline1 ... line100があり、line10を削除して、新しいline100を追加するとします。次のようになります。@@ -7,7 +7,6 @@ line6 line7 line8 line9 -this line10 to be deleted line11 line12 line13 @@ -98,3 +97,4 @@ line97 line98 line99 line100 +this is new line100
644
)は8進数で読み取られ(値はそれぞれ1、2、4の実行、書き込み、読み取りのアクセス許可)、この順序で所有者(ユーザー)、グループ、その他のアクセス許可に対応します。つまり、644
シンボリックu=rw,og=r
に書かれていれば、誰にでも読むことができますが、所有者だけが書き込めます。左側の他の数字は、シンボリックリンクのように、他の情報をエンコードします。値はgithub.com/git/git/blob/…で確認できます。この位置の最初の1は「通常のファイル」です。
既定の出力形式(元々はdiff
、より詳細な情報を探したいかのように知られているプログラムから取得される)は、「統一された差分」と呼ばれます。それは本質的に4つの異なるタイプのラインを含みます:
+
、-
および変更内容を正確に把握しているファイルの2つのバージョン間の差分を読む練習をすることをお勧めします。そのように見ると、何が起こっているのかがわかります。
私のMacの場合:
info diff
次に選択します:Output formats
-> Context
-> Unified format
-> Detailed Unified
:
または、同じセクションへの同じパスをたどるgnuのオンラインman diff:
ファイル:diff.info、ノード:詳細統一、次:統一例、上:統一フォーマット
統一フォーマットの詳細な説明................................................
統一された出力形式は、次のような2行のヘッダーで始まります。
--- FROM-FILE FROM-FILE-MODIFICATION-TIME +++ TO-FILE TO-FILE-MODIFICATION-TIME
タイムスタンプは「2002-02-21 23:30:39.942229878 -0800」のようになり、日付、小数秒の時間、およびタイムゾーンを示します。
ヘッダーの内容は `--label = LABEL 'オプションで変更できます。* Note Alternate Names ::を参照してください。
次に、1つまたは複数の違いがあります。各ハンクは、ファイルが異なる1つの領域を示しています。統一形式のハンクは次のようになります。
@@ FROM-FILE-RANGE TO-FILE-RANGE @@ LINE-FROM-EITHER-FILE LINE-FROM-EITHER-FILE...
両方のファイルに共通の行は、空白文字で始まります。2つのファイル間で実際に異なる行の左側の印刷列には、以下の標識文字の1つがあります。
`+ 'ここに最初のファイルに行が追加されました。
`-'最初のファイルから行が削除されました。
実際の差分、またはgitが出力する追加のヘッダー情報など、diffのどの部分が混乱しているのか、質問からはわかりません。念のため、ここにヘッダーの概要を示します。
最初の行は次のようなものですdiff --git a/path/to/file b/path/to/file
-明らかにそれは、diffのこのセクションが何のファイルであるかをあなたに告げるだけです。あなたはブールのconfig変数を設定した場合diff.mnemonic prefix
、a
およびは、b
のようなより説明的な文字に変更されますc
と、w
(コミットおよび作業ツリー)の。
次に、「モード行」-ファイルの内容の変更を伴わない変更の説明を提供する行があります。これには、新規/削除されたファイル、名前変更/コピーされたファイル、および権限の変更が含まれます。
最後に、のような行がありindex 789bd4..0afb621 100644
ます。おそらく気にしないでしょうが、これらの6桁の16進数は、このファイルの新旧のblobのSHA1ハッシュの省略形です(blobは、ファイルのコンテンツのような生データを格納するgitオブジェクトです)。そしてもちろん、これ100644
はファイルのモードです。最後の3桁は明らかにアクセス許可です。最初の3つは追加のファイルメタデータ情報を提供します(それについて説明するSO投稿)。
その後、(クラシックと同じようにdiff -U
)標準の統一されたdiff出力に進みます。これは、ハンクに分割されます。ハンクは、変更とそのコンテキストを含むファイルのセクションです。各塊は、一対の先行され---
且つ+++
当該ファイルを表す行、その後、実際の差分は、(デフォルト)のいずれかの側のコンテキストの三行である-
と+
除去/追加された行を示す行。
index
行。確認git hash-object ./file