补丁Patch是天才程序员、Perl的发明者Larry Wall发明的,它应高效地交流程序源代码之需求而生,随着以Linux为代表的开发源代码运行的蓬勃发展,patch这个概念已经成为开放源代码发起者、贡献者和参与者的集体无意识的一部分。patch只包含了对源代码修改的部分,这对于开放源代码社区的协同开发模式具有重要意义,意味的软件新版本的发布和对软件的缺陷或改进可以以更小的文件发布,可以减少网络的传输量,方便软件维护者的管理工作。
patch文件有多种格式,不同平台上所支持的格式不尽相同,但最常见的是context格式和unified格式。context格式被广泛使用,是patch文件格式事实上的标准。该格式包含了差异部分及其邻近的若干行,邻近就是所谓的上下文,这些行虽然没有变化,但它们出现在patch文件使得还原patch的程序具备更强的容错性。unified格式常见于GNU的patch实现,以patch形式发布的linux内核就使用了该格式。此外,还有其它比较少用的格式,如Normal格式,并排对比模式(side-by-side),ed script和RCS script模式等。除了并排对比模式方便用户观察文件差异,其它格式大多数是为了兼容旧的patch格式。
patch的工具
patch有十分丰富的工具,在Unix/Linux系统下diff/patch是最主要的patch命令行工具。另外,一些版本控制软件TortoiseCVS、 Subversion, WinMerge及集成开发环境如Eclipse包含了patch生成、应用的功能。使用命令行工具生成在Unix/Linux系统下只需要使用diff命令,在Windows下可以安装Cygwin来模拟Unix环境,当然有时候Cygwin显得过于庞大,此时可以使用unxutils,它是常用的GNU命令在Windows系统上的移植版,其中包含了diff和patch命令。从http://unxutils.sourceforge.net下载该软件包后,将其usr\local\wbin目加到Path环境变量即可使用这些命令。
产生补丁
生成patch命令用diff命令,该命令的基本用法是:
diff [选项] 旧文件或目录 新文件或目录
该命令根据选项产生新旧文件或目录之间的patch,并把该patch输出到标准输出上。
选项用来指定输出的patch文件格式,如果比较的是目录是否需要递归,对只在一边目录中存在的文件的处理方法,如何处理空格、制表符、小写等;常用选项有
-c 表示产生context格式的patch
-u 表示产生unified格式的patch
-r 表示对目录进行递归操作,用于产生整个代码树的patch
-N 表示如果文件不存在则将其等价为空文件,这个用于产生有文件增加或删除的patch
接下来,需要指定比较的对象,它们可以是文件,也可以时目录。旧版本列在前面,新版本列在后面。当然,文件或目录也可以从标准输入获得。此时,文件或目录名称用减号"-"表示。实例:
cat build.xml |diff -y -W 100 - build-1.10.xml
以每列100个字符的宽度并排对比输出build.xml和build-1.10.xml之间的差异到屏幕(标准输出)
diff -c web.xml web2.xml > web.xml.diff
产生web2.xml相对于web.xml的修改的上下文格式补丁文件到web.xml.diff中去
diff -crN src src_XFIRE > xfire-patch.diff
产生代码树src_XIRE相对于代码树src的上下文补丁文件到xfire-patch.diff中去,在src_XFIRE中新增的文件的内容也会被包含在补丁中。
打补丁
打补丁可以使用命令行工具patch。它的基本用法是:patch -pnum < 补丁文件。
打补丁时将工作目录改到需要打补丁源代码顶层目录,然后确定p后面的数字,该数字表示需要去掉的补丁文件中目录的层数,该数字和补丁创建时候工作目录和代码目录的相对位置有关,一般补丁的作者为在补丁文档中指明。如果没有指定,可以通过观察补丁文件中列出的文件完整路径和代码树中该文件所在相对路径得出。
例子:
cd src
patch -p1 < xfire-patch.diff