讀懂diff

作者: 阮一峰  發布時間: 2012-08-30 06:46  閱讀: 4383 次  推薦: 4   原文鏈接   [收藏]  

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

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

$ diff <變動前的文件> <變動后的文件>

  diff 就會告訴你,這兩個文件有何差異。它的顯示結果不太好懂,下面我就來說明,如何讀懂 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

4
0
 
標簽:diff git
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()