通過patch實現生成使用補丁

2021-05-27 19:22:50 字數 3485 閱讀 7276

一、原理

diff比較兩個檔案或檔案集合的差異,並記錄下來,生成乙個diff檔案,這也是我們常說的patch檔案,即補丁檔案。

patch能將diff檔案運用於 原來的兩個集合之一,從而得到另乙個集合。

舉個例子來說檔案a和檔案b,經過diff之後生成了補丁檔案c,那麼著個過程相當於 a -b = c ,那麼patch的過程就是b+c = a 或a-c =b。

因此我們只要能得到a, b, c三個檔案中的任何兩個,就能用diff和patch這對工具生成另外乙個檔案。

二、用法

1. diff的用法

diff後面可以接兩個檔名或兩個目錄名。 如果是乙個目錄名加乙個檔名,那麼只作用在那麼個目錄下的同名檔案。

如果是兩個目錄的話,作用於該目錄下的所有檔案,不遞迴。如果我們希望遞迴執行,需要使用-r引數。

命令diff a b >c ,一般a是原始檔案,b是修改後的檔案,c稱為a的補丁檔案。

不加任何引數生成的diff檔案格式是一種簡單的格式,這種格式只標出了不一樣的行數和內容。我們需要一種更詳細的格式,可以標識出不同之處的上下文環境,這樣更有利於提高patch命令的識別能力。這個時候可以用-c開關。

通常的引數為 -nuar。

2. patch的用法

patch用於根據原檔案和補丁檔案生成目標檔案。還是拿上個例子來說

patch a c 就能得到b, 這一步叫做對a打上了b的名字為c的補丁。

之一步之後,你的檔案a就變成了檔案b。如果你打完補丁之後想恢復到a怎麼辦呢?

patch -r b c 就可以重新還原到a了。

所以不用擔心會失去a的問題。

其實patch在具體使用的時候是不用指定原檔案的,因為補丁檔案中都已經記載了原檔案的路徑和名稱。 patch足夠聰明可以認出來。但是有時候會有點小問題。比如一般對兩個目錄diff的時候可能已經包含了原目錄的名字,但是我們打補丁的時候會進入到目 錄中再使用patch,著個時候就需要你告訴 patch命令怎麼處理補丁檔案中的路徑。可以利用-pn開關,告訴patch命令忽略的路徑分隔符的個數。舉例如下:

a檔案在 dir_a下,修改後的b檔案在dir_b下,一般dir_a和dir_b在同一級目錄。我們為了對整個目錄下的所有檔案一次性diff,我們一般會到dir_a和dir_b的父目錄下執行以下命令

diff -rc dir_a dir_b >c

這個時候補丁檔案c中會記錄了原始檔案的路徑為 dir_a/a

現在另乙個使用者得到了a檔案和c檔案,其中a檔案所在的目錄也是dir_a。 一般,他會比較喜歡在dir_a目錄下面進行patch操作,它會執行

patch

但是這個時候patch分析c檔案中的記錄,認為原始檔案是 dir_a/a,但實際上是./a,此時patch會找不到原始檔案。為了避免這種情況我們可以使用-p1引數如下

patch -p1

此時,patch會忽略掉第1個」/」之前的內容,認為原始檔案是 ./a,這樣就正確了。

最後有以下幾點注意:

1. 一次打多個patch的話,一般這些patch有先後順序,得按次序打才行。

2. 在patch之前不要對原檔案進行任何修改

3. 如果patch中記錄的原始檔案和你得到的原始檔案版本不匹配(很容易出現),那麼你可以嘗試使用patch, 如果幸運的話,可以成功。大部分情況下,會有不匹配的情況,此時patch會生成rej檔案,記錄失敗的地方,你可以手工修改。

三、舉例

通常情況下,diff與patch一起使用。即使用patch呼叫diff檔案。如下面這個例子:

有兩個目錄為old和new,old中有f1.c,f2.c;new中有f1.c,f3.c。現要將new補到old上。

[fsy@localhost ~]$ mkdir old new

[fsy@localhost ~]$ cd old

[fsy@localhost old]$ touch f1.c f2.c

###建立兩個資料夾和old中的檔案

[fsy@localhost old]$ echo 1 > f1.c

[fsy@localhost old]$ cat f1.c

1[fsy@localhost old]$ echo 2 > f2.c

###在old的檔案中寫入內容

[fsy@localhost old]$ cd ../new

[fsy@localhost new]$ touch f1.c f3.c

[fsy@localhost new]$ echo new 1 > f1.c

[fsy@localhost new]$ cat f1.c

new 1

[fsy@localhost new]$ echo 3 > f3.c

###建立new檔案並寫入內容

[fsy@localhost new]$ cd ..

[fsy@localhost ~]$ diff -nuar old new >dir.diff

[fsy@localhost ~]$ cat dir.diff

diff -nuar ./old/f1.c ./new/f1.c

---   old/f1.c    2011-08-30 12:32:21.553737454 +0800

+++  new/f1.c    2011-08-30 12:34:28.444148124 +0800

@@ -1 +1 @@

-1+new 1

diff -nuar ./old/f2.c ./new/f2.c

---   old/f2.c    2011-08-30 12:32:40.334207279 +0800

+++   new/f2.c    1970-01-01 08:00:00.000000000 +0800

@@ -1 +0,0 @@

-2diff -nuar ./old/f3.c ./new/f3.c

---   old/f3.c    1970-01-01 08:00:00.000000000 +0800

+++   new/f3.c    2011-08-30 12:34:42.331754293 +0800

@@ -0,0 +1 @@+3

###可以清楚的看見兩個資料夾下檔案的不同之處

[fsy@localhost ~]$ cd old ..........................................必須進入到要打補丁的資料夾

[fsy@localhost old]$ patch -p1 < ../dir.diff

patching file old/f1.c

patching file old/f2.c

patching file old/f3.c

[fsy@localhost old]$ ls

f1.c  f3.c

[fsy@localhost old]$ cat f1.c

new 1

[fsy@localhost old]$ cat f3.c

3[fsy@localhost old]$

###f2.c被刪除,f1.c和f3.c被更新。

通過 git diff 生成 patch 補丁

以未提交的修改為例 git diff feature a.patch但是,如果有新增的檔案,並不在 git 管理之內 git diff cached feature a.patch如果還包含二進位制檔案,例如等 git diff cached binary feature a.patch應用 pat...

如何使用git 生成patch

git clone git cd bluetooth next 2.6 2,修改 vi drivers bluetooth btusb.c 3,把 新增到git管理倉庫 git add drivers bluetooth btusb.c 4,提交修改 git commit m added ather...

patch補丁檔案製作 使用和常見問題

1.給原始碼樹加 patch 進入原始碼樹的根目錄下 cd src dir patch p 1 path to your patch p 1 指定忽略的目錄個數,如你的patch頭為 diff urn orig include linux module.h tgt include linux mod...