diff 命令是 Linux 上很是重要的工具,用於比較文件甚至目錄的內容,清晰的告訴你先後改動的地方。diff 能夠輸出爲補丁(patch) ,Linux 中還有一條命令patch,能夠根據補丁文件,對文件更新修改。當你和別人合做或想爲開源項目提供貢獻時,能夠將本身的修改打成補丁,郵件給合做者,他便可合併你的代碼。所以diff也是svn、cvs、git等版本控制工具不可或缺的一部分。 git
diff的基本格式以下: github
$ diff [參數] <變更前的文件> <變更後的文件>
命令參數有如下經常使用的一些,能夠根據不一樣的模式選用: vim
-b 或--ignore-space-change 不檢查空格字符的不一樣。 -B 或--ignore-blank-lines 不檢查空白行。 -w 或--ignore-all-space 忽略所有的空格字符。 -i 或--ignore-case 不檢查大小寫的不一樣。 -q 或--brief 僅顯示有無差別,不顯示詳細的信息。
在diff目錄時經常使用的參數以下: svn
-r 或--recursive 比較子目錄中的文件。 -N 或--new-file 文件A僅出如今某個目錄中,預設會顯示:Only in目錄 文件A若使用-N參數,則diff會將文件A與一個空白的文件比較。 -P或--unidirectional-new-file 與-N相似,只有當第二個目錄包含了一個第一個目錄所沒有的文件時, 纔會將這個文件與空白的文件作比較。
diff有大概四種格式:正常格式、並列格式、上下文格式、合併格式。 工具
還有git diff與vimdiff模式。 ui
diff能夠比較文本文件或目錄之間的差別,首先來說解文本文件之間的diff,示例文件以下: spa
文件f1 插件
a b b c d e
文件f2 3d
a b c b d e f
正常格式不用加任何參數,diff f1 f2便可,顯示結果以下: 版本控制
1c1 < a b --- > a b c 3d2 < c 5a5 > f
1c一、3d二、5a5是說明變更的位置,前邊數字表明f1中變化的行,後邊的則表明f2中變化的行,中間的字母分別表明「改變」(c)、「刪除」(d)和「增長」(a)。
<表示f1指定行的內容,---分割兩個文件的,而後>表示f2指定行的內容。刪除或增長時,則分別f二、f1中指定行無內容。
其餘格式diff都是前後顯示兩個文件的內容變化,並列格式能夠並排顯示兩個文件的內容變化,更形象的看出文件的變化,和vimdiff顯示的有些類似。
使用方法爲加入-y參數,便可並列顯示,-W num參數可設定並列的寬度,能夠不使用。
diff -y -W 50 f1 f2
結果以下:
a b | a b c b b c < d d e e > f
|說明此行有變化,<說明此行被刪除了,>說明此行是後增長的。
標準格式diff顯示的內容不夠直觀,上下文格式則經過顯示變化的上下文,而更加的利於理解。
使用方法爲使用參數-c參數: diff -c f1 f2,結果以下:
*** f1 2014-04-03 21:24:23.581007082 +0800 --- f2 2014-04-03 21:24:21.324995895 +0800 *************** *** 1,5 **** ! a b b - c d e --- 1,5 ---- ! a b c b d e + f
首先,顯示兩個文件的基本狀況:
*** f1 2014-04-03 21:24:23.581007082 +0800 --- f2 2014-04-03 21:24:21.324995895 +0800
***表示變更前的文件f1,---表示變更後的文件f2。
而後,15個星號將文件的基本狀況與變更內容分割開。
最後,顯示f1和f2文件的內容變更狀況。
*** 1,5 ****表示f1文件的1~5行
--- 1,5 ----表示f2文件的1~5行
!表明次行內容有變更,+表示此行爲新增長,-表示此行被刪除了。
上下文格式默認顯示包括修改行先後的三行內容,可使用-num來設置顯示先後num行,如:
diff -c -1 f1 f2
兩個文件大量內容重複,上下文格式將顯示不少無用干擾信息,後來就退出了合併式diff。
使用方法爲,加入-u參數,diff -u f1 f2,結果以下:
--- f1 2014-04-03 21:24:23.581007082 +0800 +++ f2 2014-04-03 21:24:21.324995895 +0800 @@ -1,5 +1,5 @@ -a b +a b c b -c d e +f
一樣前兩行表示兩個文件的基本狀況
而後@@ -1,5 +1,5 @@表示修改的位置,-表明 f1 的1~5行,+表明 f2 的1~5行。
最後是合併顯示的變更具體內容,依舊是-表明f1,+表明f2。
同上下文格式同樣,合併格式也是默認顯示修改先後3行的內容,也可使用-num來設置顯示先後num行:
diff -u -1 f1 f2
這裏還要提到,git使用的是合併格式diff的變體。當前工做目錄下git add f1後,修改f1的內容,可使用以下命令,觀察作出的修改
git diff
結果以下:
diff --git a/f1 b/f1 index 924a897..c3b09ff 100644 --- a/f1 +++ b/f1 @@ -1,5 +1,5 @@ -a b +a b c b -c d e +f
和合並格式diff的區別在頭部文件基本信息,git diff顯示的是a、b兩個版本的f1文件的內容變化,而且顯示了兩個版本的git哈希值(924a897..c3b09ff),與文件的權限(644)。
Vim提供的diff模式稱做imdiff,能夠很清晰形象的觀察到文件內容的變化,方便的進行合併工做。vimdiff的使用方法以下:
vimdiff f1 f2 或者 vim -d f1 f2
下圖爲結果的畫面
默認屏幕垂直分割,對比顯示兩個文件的不一樣,若是想要水平分割可使用參數-o(不過怎麼也是垂直的好看)。這裏能夠看到f1和f2中都有的可是內容改變的行被高亮爲紅色,次行內修改的具體位置被高亮爲黃色;f1裏有可是在f2中被刪除的行,f1中顯示爲藍色,f2中顯示爲綠色;相反,f2中增長的行顯示爲藍色,f1中相應位置顯示爲綠色。這樣更突出引發差別的地方,而且若是文件內容較多,連續相同的行會摺疊起來,可使用zo和zc打開和關閉摺疊。
對不一樣修改內容的高亮顯示,顏色能夠本身自定義,在本身的Vim配置文件~/.vimrc中添加以下語句:
hi DiffAdd ctermbg=blue ctermfg=white hi DiffDelete ctermbg=green ctermfg=none hi DiffChange ctermbg=red ctermfg=White hi DiffText ctermbg=yellow ctermfg=black
使用GUI的話能夠配置guibg和guifg。
切換不一樣的窗口可使用下列命令:
Ctrl-w l 切換到右邊窗口 Ctrl-w h 切換到左邊窗口 Ctrl-w j 切換到下邊窗口 Ctrl-w k 切換到上邊窗口
在編輯文件時也可使用命令模式啓動vimdiff模式:
vim f1 :vertical diffsplit f2
若是不加vertical默認使用的水平分割。在Vim中除了diffsplit還有一些其餘的命令,利於對文件進行合併和其餘操做。
:diffget 把差別點中另外一個文件對應的內容複製到當前行 :diffput 把差別點中當前行的內容複製到另外一個文件對應的位置 :diffpatch 根據補丁文件更新文件內容,後面須要跟一個參數指定文件 :diffupdate 手動刷新比較結果 :qa 同時退出兩個文件 :wqa 同時保存並退出
若是Vim安裝來vim-fugitive插件,還可使用:Gdiff命令來比較當前文件和暫存區中的文件的不一樣,也是利用的vimdiff,顯示和操做同上。
目錄間的diff比較目錄中相同文件名的文件,也可使用正常格式、上下文格式、合併格式、並列格式。
示例目錄爲d1和d2目錄,d1中有文件f一、f3,d2中有f一、f2,其中f1有一些改動。
若是不是用其餘參數,不會遞歸比較子目錄中的文件,會顯示只存在目錄一個目錄中的文件,但不顯示其詳細信息,以下結果是使用diff -u d1 d2的結果:
diff -u d1/f1 d2/f1 --- d1/f1 2014-04-03 19:29:25.910803383 +0800 +++ d2/f1 2014-04-03 19:28:52.918639783 +0800 @@ -1,5 +1,5 @@ -a b c +a b b +c d e -f 只在 d2 存在:f2 只在 d1 存在:f3
在目錄的diff中常使用的參數是-ruN,r表示遞歸比較子目錄中的文件,u是合併格式,N表示diff會將只存在與某個目錄中的文件與一個空白的文件比較。
將diff的輸出重定向到文本文件中,即獲得補丁文件(patch),可使用patch命令對文本文件或目錄打補丁,從而進行內容更新。
patch的基本用法
patch [參數] <patchfile>
參數:
-p Num 忽略幾層文件夾 -E 選項說明若是發現了空文件,那麼就刪除它 -R 取消打過的補丁。
若是使用參數-p0,表示從當前目錄找打補丁的目標文件夾,再對該目錄中的文件執行patch操做。 而使用參數-p1,表示忽略第一層目錄,從當前目錄尋找目標文件夾中的子目錄和文件,進行patch操做。
產生補丁
diff -uN f1 f2 > file.patch
打補丁
patch -p0 < file.patch 或者 patch f1 file.patch
取消補丁
patch -RE -p0 < file.patch 或者 patch -RE f1 file.patch
產生補丁
diff -urN d1 d2 > dir.patch
打補丁
cd d1 patch -p1 < ../dir.patch
取消補丁
patch -R -p1 < ../dir.patch
應用補丁時的目標代碼和生成補丁時的代碼未必相同,打補丁操做可能失敗,補丁失敗的文件會以.rej結尾。