patch和diff的用法


在FreeBSD下用ports安装软件时经常可以看到make在下载完的程序代码上打了一个又一个补丁。尤其是安装vim时,补丁甚至多达几百个。
那么这些补丁是怎么制作的,又是怎么打上去的呢。
(下面的实验在MacOS X下进行,当然在FreeBSD下也是一样的)

先来说制作补丁,这可是patch的兄弟diff的得意本领。
首先让我们建立两个文件,分别取名week和week.new,然后用下面的命令打开它们比较一下:

$vim -d week week.new

显示结果如下:

从图中我们可以看到它们的区别。
然后我们可以用下面的命令建立patch文件:

$diff -c week week.new > week.patch

建立好的week.patch如下:

*** week	2010-04-17 18:10:14.000000000 +0900
--- week.new	2010-04-17 18:10:14.000000000 +0900
***************
*** 1,7 ****
  Sunday
! Monkeyday
  Tuesday
  Wednesday
  Thursday
  Saturday
- Sunday
--- 1,7 ----
  Sunday
! Monday
  Tuesday
  Wednesday
  Thursday
+ Friday
  Saturday

或者我们还可以用下面的命令建立更简洁的patch文件:

$diff -u week week.new > week.patch

这次建立好的week.patch是这样的:

--- week	2010-04-17 18:10:14.000000000 +0900
+++ week.new	2010-04-17 18:10:14.000000000 +0900
@@ -1,7 +1,7 @@
 Sunday
-Monkeyday
+Monday
 Tuesday
 Wednesday
 Thursday
+Friday
 Saturday
-Sunday

第一种格式是把整个文件分列上下两部分,分别表示它们的区别。
第二种格式仅把整个文件中不同的地方表示出来,缩小了patch文件的尺寸。
无论是使用-c还是-u选项,它们都会默认记录包括差异在内的至少3行信息。
那是因为:patch需要起码2行信息,才能够在目标文件中准确找出需要打补丁的位置。

接下来就是使用patch了。

$patch < week.patch

执行了这条命令后,week文件就和week.new文件完全一致了。

需要注意的是,patch命令一般不指定文件名。
patch命令参照patch文件中记录的文件名来决定对哪个文件打补丁。
并且,patch会选择文件名较短的那个文件作为操作对象。
所以在进行diff前,必须特意对最新的文件赋予相对更长的文件名。

有时候,制作patch文件时所处的目录和执行patch时所处的目录并不一致。
例如,在一个开发项目中,为了方便管理,patch文件被统一制作在项目的某个目录下。

$pwd
/Users/bear/Program/patch_test
$ls -R
workdir

./workdir:
week		week.new
$diff -u workdir/week workdir/week.new > week.patch
$cd workdir

此时,我们在workdir目录下。该目录下有我们需要打补丁的文件week,并且补丁文件week.patch在上一级目录。
我们可以用-p开关来告诉patch,当看到patch文件内的目标文件时,应该从第几级目录开始操作。

patch文件的内容如下:

--- workdir/week        2010-04-17 20:24:14.000000000 +0900
+++ workdir/week.new    2010-04-17 20:24:14.000000000 +0900
@@ -1,7 +1,7 @@
 Sunday
...

而patch命令应该这样执行:

$patch -p1 < ../week.patch

-p后面的1就是告诉patch,当看到patch文件中的workdir/week时,忽略第一级目录workdir,而将week作为patch操作的目标文件。
当你有多级目录的时候,就可以根据所处目录的层级,任意调整-p后的数字,完成对目标文件的补丁操作了。

Tagged on: ,

One thought on “patch和diff的用法

发表评论

电子邮件地址不会被公开。