若我們發現項目有bug,而自己沒有代碼提交權限,此時最合適的解決方法就是用diff命令做一個補丁分發給項目成員。項目成員通過patch命令可瞭解你的意圖。
Patch 過程:
(1) 用diff工具比較新舊代碼,生成patch文件(diff功能就是用來比較兩個文件不同,然後記錄下來);
(2) 使用patch命令,將patch文件合併到原有代碼;
(3) 檢查是否存在無法patch的文件,修改或重新選擇是否對其做patch。patch打完就可以直接編譯了。通常在makefile中加入patch命令,然後編譯代碼。
補丁頭分別用—/+++來表示要打補丁的文件。 — 開頭表示舊文件, +++ 開頭表示新文件。
一個補丁文件可能包含以 —/+++ 開頭的很多節,每一節用來打一個補丁。所以一個補丁文件中可包含好多個補丁。
塊是補丁中要修改的地方,他們通常以@@開始,用來表示要修改的位置。結束於另一個塊的開始或者一個新的補丁頭。塊會縮進一列,而這一列是用來表示這一行是要增加還是要刪除的。塊的第一列:
+號表示這一行是要加上的。
-號表示這一行是要刪除的。
沒有加號也沒有減號表示這裏只是引用的而不需要修改。
打補丁
1、爲單個文件生成補丁
diff -up linux-4.9/net/sunrpc/svc.orig.c linux-4.9/net/sunrpc/svc.c > patch
參數:
-u 顯示有差異行的前後幾行(上下文), 默認是前後各3行, 這樣, patch中帶有更多的信息.
-p 顯示代碼所在的函數的信息.
- 爲多個文件生成補丁
diff -uprN linux-4.9.orig/net/sunrpc/ linux-4.9/net/sunrpc/ > patch
這條命令對比了linux-2.6.28.8.orig/net/sunrpc/和linux-2.6.28.8/net/sunrpc/兩個目錄下的所有源碼差異.
參數詳解:
-r 遞歸地對比一個目錄和它的所有子目錄(即整個目錄樹).
-N 如果某個文件缺少了, 就當作是空文件來對比. 如果不使用本選項, 當diff發現舊代碼或者新代碼缺少文件時, 只簡單的提示缺少文件. 如果使用本選項, 會將新添加的文件全新打印出來作爲新增的部分.
生成的補丁中, 路徑信息包含了你的Linux源碼根目錄的名稱, 但其他人的源碼根目錄可能是其它名字, 所以, 打補丁時, 要進入你的Linux源碼根目錄, 並且告訴patch工具, 請忽略補丁中的路徑的第一級目錄(參數-p1).
$ patch -p1 < patch1
diff命令必須在整個Linux源碼的根目錄的上一級目錄中執行.
示例:
給修改過的內核生成patch,然後用生成的patch給未修改過的內核打補丁。
其中,目錄linux-4.9爲未修改過的內核,目錄linux-4.9_1爲修改過的內核
1 $ diff -uparN linux-4.9 linux-4.9_1/ > mypatch
2 $ cd linux-4.9
3 $ patch -p1 < mypatch
打完補丁後,需要檢查一下有沒有拒絕執行的文件,即檢查.rej文件的存在。使用命令:
$find . -name *.rej
如果發現,會將其輸出到標準輸出終端,默認屏幕。當然,你也可以採用重定向,輸出到指定文件,比如reject。
$fine . -name *.rej >reject
然後可以查看reject的內容了。
Android補丁的生成和應用:
把某個commit做成補丁:
git format-patch -1 指定commit號 //生成指定commit號的補丁
git format-patch -3 //從當前分支最新提交點往下共生成3個補丁
應用補丁
git apply test.patch