Linux下的一些開源的軟件源碼包釋放時會有一個軟件包和補丁文件,我們根據需求可以選擇是否對這個軟件包進行打補丁。同時,有時為了記錄對一些比較龐大的軟件工程的源碼的更改位置時,也會將自己對源代碼的更改的生成補丁文件。補丁文件便於釋放給別人,也可以記錄我們對源碼更改的位置,便於我們后期進行追溯。因此,學習如何制作補丁文件和打補丁操作很有意義。
1、補丁生成
補丁文件是通過diff命令生成的,生成補丁文件的命令使用格式如下:
diff -uNr src modify > patch_file
對於diff命令,它的功能就是逐行比較兩個文件的不同,然后輸出比較的結果。如果將diif輸出的比較結果保存到某個文件中,這個文件也就是所謂的diff補丁文件
命令選項:
- -u:選項以統一格式創建補丁文件,這種格式比缺省格式更緊湊些
- -N:選項確保補丁文件將正確地處理已經創建和刪除文件的情況
- -r:遞歸選項,設置了這個選項,diff會將兩個不同版本源代碼目錄中的所有對應文件全部都進行一次比較,包括子目錄文件
FILES:
- src:源文件(目錄),未進行修改的
- modify:基於src,根據需求對里面的文件內容修改之后結果
">" 是重定向符號,表示將diff比較的結果重定向輸入到patch_file文件中(如不指定重定向,diff的結果將打印到標准輸出),patch_file文件一般指定以.patch為后綴。
上述的補丁命令的功能就是逐個比較源文件(夾)和目標文件(夾)的所有文件,將差異信息記錄到patch_file中,patch_file文件也就是我們所謂的補丁文件。
2、打補丁
有了補丁文件那么就可以來進行打補丁操作了,打補丁是通過patch命令完成的。一般情況下,打補丁命令使用格式如下(這里只介紹了對源文件(夾)進行打補丁操作):
patch -pN < xxx.patch
xxx.patch文件是上面diff命令生成的補丁文件,打補丁就是patch利用diff制作的補丁來實現源文件(夾)和目的文件(夾)的轉換。這樣說就意味着你可以從源文件(夾)到目的文件(夾),也可以目的文件(夾)到源文件(夾)。一般情況下,我們都是將源文件打補丁到我們修改后的目的文件。
選項:
- -pN:選項打補丁時要忽略掉第N層目錄
這里還是以實例來說明-pN選項的作用,假如補丁文件內有這樣格式內容:
diff -uNr src/bsp/bsp_led.c modify/bsp/bsp_led.c
當我們在src目錄下進行打補丁時,此時打補丁所在的目錄是在src目錄,它從當前目錄下可以尋找bsp的文件夾,在它下面找bsp_led.c,所以此時需要用-p1來指定忽略第一個/前的目錄(這里用到的是相對路徑)。
3、簡單測試
創建src目錄及各目錄下的文件,將src目錄內容拷貝到modify目錄,修改modify目錄里的各個源文件。
目錄層次信息如下所示:
├── modify
│ ├── bsp
│ │ ├── bsp_led.c
│ │ └── bsp_uart.c
│ └── main.c
├── src
│ ├── bsp
│ │ ├── bsp_led.c
│ │ └── bsp_uart.c
│ └── main.c
使用diff命令生成補丁文件,補丁文件名src_20210416.patch
diff -uNr src/ modify/ > src_20210416.patch
src_20210416.patch補丁文件內容格式如下:
diff -uNr src/bsp/bsp_led.c modify/bsp/bsp_led.c ------------------->① --- src/bsp/bsp_led.c 2021-04-16 09:07:19.638716463 +0800 -------->② +++ modify/bsp/bsp_led.c 2021-04-16 09:48:08.966764603 +0800 @@ -1,7 +1,9 @@-------------------->③ #include "bsp_led.h" - -------------------------------->④ +/* + * @brief: led initialization + */ void bsp_led_init(void) { - + }
① 表示下面內容是哪個源文件和目標文件的比較結果
② '---'表示的是源文件是哪個,'+++'表示的是目標文件是哪個
③ 源文件和目標文件差異位置描述,-1,7表示源文件的1到7行,+1,9表示目標文件的1到9行
④ -表示源文件中該位置本來內容,+表示將源文件中的內容要替換成的內容
使用patch命令對src文件進行打補丁,打補丁完成后,src中的各文件內容和modify中各文件的內容一致了。
patch -p0 < src_20210416.patch
測試目錄下各文件內容
src目錄:

int main(int argc, char **argv) { return 0; }

#include "bsp_led.h" void bsp_led_init(void) { }

#include "bsp_uart.h" void bsp_uart_init(void) { }
modify目錄:

#include "bsp_uart.h" #include "bsp_led.h" int main(void) { bsp_led_init(); bsp_uart_init(); while(1) { } return 0; }

#include "bsp_led.h" /* * @brief: led initialization */ void bsp_led_init(void) { }

#include "bsp_uart.h" /* * @brief: uart initialization */ void bsp_uart_init(void) { }