在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后的数字,完成对目标文件的补丁操作了。
谢谢分享,收获很大~