天天看點

linux diff詳解

diff是Unix系統的一個很重要的工具程式。

它用來比較兩個文本檔案的差異,是代碼版本管理的基石之一。你在指令行下,輸入:

  $ diff <變動前的檔案> <變動後的檔案>

diff就會告訴你,這兩個檔案有何差異。它的顯示結果不太好懂,下面我就來說明,如何讀懂diff。

linux diff詳解

一、diff的三種格式

由于曆史原因,diff有三種格式:

  * 正常格式(normal diff)

  * 上下文格式(context diff)

  * 合并格式(unified diff)

我們依次來看。

二、示例檔案

為了便于講解,先建立兩個示例檔案。

第一個檔案叫做f1,内容是每行一個a,一共7行。

  a

  a

  a

  a

  a

  a

  a

第二個檔案叫做f2,修改f1而成,第4行變成b,其他不變。

  a

  a

  a

  b

  a

  a

  a

三、正常格式的diff

現在對f1和f2進行比較:

  $ diff f1 f2

這時,diff就會顯示正常格式的結果:

  4c4

  < a

  ---

  > b

第一行是一個提示,用來說明變動位置。

  4c4

它分成三個部分:前面的"4",表示f1的第4行有變化;中間的"c"表示變動的模式是内容改變(change),其他模式還有"增加"(a,代表addition)和"删除"(d,代表deletion);後面的"4",表示變動後變成f2的第4行。

第二行分成兩個部分。

  < a

前面的小于号,表示要從f1當中去除該行(也就是第4行),後面的"a"表示該行的内容。

第三行用來分割f1和f2。

  ---

第四行,類似于第二行。

  > b

前面的大于号表示f2增加了該行,後面的"b"表示該行的内容。

最早的Unix(即AT&T版本的Unix),使用的就是這種格式的diff。

四、上下文格式的diff

上個世紀80年代初,加州大學伯克利分校推出BSD版本的Unix時,覺得diff的顯示結果太簡單,最好加入上下文,便于了解發生的變動。是以,推出了上下文格式的diff。

它的使用方法是加入c參數(代表context)。

  $ diff -c f1 f2

顯示結果如下:

  *** f1 2012-08-29 16:45:41.000000000 +0800

  --- f2 2012-08-29 16:45:51.000000000 +0800

  ***************

  *** 1,7 ****

   a

   a

   a

  !a

   a

   a

   a

  --- 1,7 ----

   a

   a

   a

  !b

   a

   a

   a

這個結果分成四個部分。

第一部分的兩行,顯示兩個檔案的基本情況:檔案名和時間資訊。

  *** f1 2012-08-29 16:45:41.000000000 +0800

  --- f2 2012-08-29 16:45:51.000000000 +0800

"***"表示變動前的檔案,"---"表示變動後的檔案。

第二部分是15個星号,将檔案的基本情況與變動内容分割開。

  ***************

第三部分顯示變動前的檔案,即f1。

  *** 1,7 ****

   a

   a

   a

  !a

   a

   a

   a

這時不僅顯示發生變化的第4行,還顯示第4行的前面三行和後面三行,是以一共顯示7行。是以,前面的"*** 1,7 ****"就表示,從第1行開始連續7行。

另外,檔案内容的每一行最前面,還有一個标記位。如果為空,表示該行無變化;如果是感歎号(!),表示該行有改動;如果是減号(-),表示該行被删除;如果是加号(+),表示該行為新增。

第四部分顯示變動後的檔案,即f2。

  --- 1,7 ----

   a

   a

   a

  !b

   a

   a

   a

除了變動行(第4行)以外,也是上下文各顯示三行,總共顯示7行。

五、合并格式的diff

如果兩個檔案相似度很高,那麼上下文格式的diff,将顯示大量重複的内容,很浪費空間。1990年,GNU diff率先推出了"合并格式"的diff,将f1和f2的上下文合并在一起顯示。

它的使用方法是加入u參數(代表unified)。

  $ diff -u f1 f2

顯示結果如下:

  --- f1 2012-08-29 16:45:41.000000000 +0800

  +++ f2 2012-08-29 16:45:51.000000000 +0800

  @@ -1,7 +1,7 @@

   a

   a

   a

  -a

  +b

   a

   a

   a

它的第一部分,也是檔案的基本資訊。

  --- f1 2012-08-29 16:45:41.000000000 +0800

  +++ f2 2012-08-29 16:45:51.000000000 +0800

"---"表示變動前的檔案,"+++"表示變動後的檔案。

第二部分,變動的位置用兩個@作為起首和結束。

  @@ -1,7 +1,7 @@

前面的"-1,7"分成三個部分:減号表示第一個檔案(即f1),"1"表示第1行,"7"表示連續7行。合在一起,就表示下面是第一個檔案從第1行開始的連續7行。同樣的,"+1,7"表示變動後,成為第二個檔案從第1行開始的連續7行。

第三部分是變動的具體内容。

   a

   a

   a

  -a

  +b

   a

   a

   a

除了有變動的那些行以外,也是上下文各顯示3行。它将兩個檔案的上下文,合并顯示在一起,是以叫做"合并格式"。每一行最前面的标志位,空表示無變動,減号表示第一個檔案删除的行,加号表示第二個檔案新增的行。

六、git格式的diff

版本管理系統git,使用的是合并格式diff的變體。

  $ git diff

顯示結果如下:

  diff --git a/f1 b/f1

  index 6f8a38c..449b072 100644

  --- a/f1

  +++ b/f1

  @@ -1,7 +1,7 @@

   a

   a

   a

  -a

  +b

   a

   a

   a

第一行表示結果為git格式的diff。

  diff --git a/f1 b/f1

進行比較的是,a版本的f1(即變動前)和b版本的f1(即變動後)。

第二行表示兩個版本的git哈希值(index區域的6f8a38c對象,與工作目錄區域的449b072對象進行比較),最後的六位數字是對象的模式(普通檔案,644權限)。

  index 6f8a38c..449b072 100644

第三行表示進行比較的兩個檔案。

  --- a/f1

  +++ b/f1

"---"表示變動前的版本,"+++"表示變動後的版本。

後面的行都與官方的合并格式diff相同。

  @@ -1,7 +1,7 @@

   a

   a

   a

  -a

  +b

   a

   a

   a

七、閱讀材料

  * diff - Wikipedia

  * How to read a patch or diff

  * How to work with diff representation in git

(完)

本文轉自http://www.ruanyifeng.com/blog/2012/08/how_to_read_diff.html

繼續閱讀