diff 是 Unix 系統的一個很重要的工具程序。
它用來比較兩個文本文件的差異,是代碼版本管理的基石之一。你在命令行下,輸入:
$ diff
diff 就會告訴你,這兩個文件有何差異。它的顯示結果不太好懂,下面我就來說明,如何讀懂 diff。
一、diff 的三種格式
由於歷史原因,diff 有三種格式:
* 正常格式(normal diff)
* 上下文格式(context diff)
* 合併格式(unified diff)
我們依次來看。
二、示例文件
為了便於講解,先新建兩個示例文件。
第一個文件叫做 f1,內容是每行一個a,一共 7 行。
a
a
a
a
a
a
第二個文件叫做 f2,修改 f1 而成,第 4 行變成b,其他不變。
a
a
a
b
a
a
a
現在對 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"表示該行的內容。
最早的 (即 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
七、閱讀材料
*
*
*
閱讀更多 遊聚網
的文章
關鍵字:
F1賽車
UNIX
讀懂