diff/patch命令以及quilt工具的使用

diff命令

diff [option] file1 file2

按“行”比较两个文件的差异。可以比较文件或目录。

option:
-c: 完整的显示两个文件不同行的上下文
-c -C num: 显示上下文的行数,默认为3
-u: 以unified格式显示不同
-u -U num: 显示上下文的行数,默认为3
-p:如果不同在函数中,则提示所在函数名
-r:递归的比较所有子目录
-N:视不存在的文件为空文件来比较
-x PATTERN: 忽略PATTERN匹配的文件

例如,比较compdir01和compdir03两个文件夹,忽略其中的.patch文件:

diff -u compdir01 compdir03 -x *.patch

-X patternfiles: 忽略patternfiles文件中指定的所有PATTERN
[root@ubuntu]others:$ cat patternfiles 
main.c
backtrace.h
diff -u compdir01 compdir03 -X patternfiles

生成一个patch:

diff -u compdir01 compdir03 > compdir.patch


patch命令

打patch:
patch -pN < compdir.patch
其中N为需要剥掉的文件名中的目录级数,例如,compdir.patch文件中指明的文件名为:
/home/myname/personale/compdir01/backtrace.c
而你的backtrace.c文件在/home/yourname/compdir01/目录下,
那你就需要将patch拷贝到/home/yourname/目录下,然后执行
patch -p3 < compdir.patch
即剥掉patch文件中的/home/myname/personale/前缀。
或者将patch拷贝到/home/yourname/compdir01/目录下,然后执行
patch -p4 < compdir.patch
即剥掉patch文件中的/home/myname/personale/compdir01/前缀。

记住,打patch的时候不要过分依赖patch命令,打完之后一定要检查代码。另外,尽量在原始项目中打patch,避免冲突。


quilt命令

quilt命令同样具有生成补丁和应用补丁的功能,但它的优势是还可以作为管理补丁的工具。一个比较大的项目可能由不同开发者共同维护,其中很多修改都以补丁的方式提供,这些补丁可能存在依赖关系。
quilt工具在源代码目录中生成一个patches/目录,里面存放所有可用的补丁,记录了所有patches的先后顺序,并提供了一系列操作这些补丁的命令。

quilt以栈的形式管理补丁,最先打上的补丁位于栈底,最后打上的补丁位于栈顶(top)。打patch的动作称为push,取消补丁的动作称为pop。就如下图所示,项目中有5个patch,最新的patch为e.patch,所以quilt将这个patch放在栈顶,通过维护这样一个结构,quilt可以继续打新patch或按顺序回退patch。

diff/patch命令以及quilt工具的使用_第1张图片

源代码的patch文件的先后顺序可以查看patches/目录下的series文件。

了解了top、push和pop的概念,下面我们就来看一下quilt命令的用法。
例如在一个原始目录中有下列文件:
[root@ubuntu]compdir01:$ ls
backtrace.c backtrace.h kernfiles 
main.c Makefile uallsyms.c

我现在要修改main.c,并生成patch:
[root@ubuntu]compdir01:$ quilt new 00-bt.patch
Patch 00-bt.patch is now on top
[root@ubuntu]compdir01:$ quilt add main.c
File main.c added to patch 00-bt.patch
 这样,就新建了patch文件00-bt.patch,并关联了源文件main.c。注:如果要解除文件和当前patch的关联,使用quilt remove,如quilt remove main.c。修改main.c,增加几行打印信息。修改后,执行: 
  
[root@ubuntu]compdir01:$ quilt refresh
Refreshed patch 00-bt.patch
在patches目录下就生成了00-bt.patch文件。
quilt refresh命令用来更新位于top的patch文件,也可以指定现有的patch文件。

接下来,我想增加一个函数,并在main.c中测试,需要修改的文件为main.c backtrace.h backtrace.c
[root@ubuntu]compdir01:$ quilt new 02-bt-addr2name.patch
Patch 02-bt-addr2name.patch is now on top
[root@ubuntu]compdir01:$ quilt add main.c backtrace.h backtrace.c
File main.c added to patch 02-bt-addr2name.patch
File backtrace.h added to patch 02-bt-addr2name.patch
File backtrace.c added to patch 02-bt-addr2name.patch
此时修改代码,然后生成patch:
[root@ubuntu]compdir01:$ quilt refresh
Refreshed patch 02-bt-addr2name.patch

下面我们再生成一个patch:
[root@ubuntu]compdir01:$ quilt new 03-bt-delcomments.patch
Patch 03-bt-delcomments.patch is now on top
[root@ubuntu]compdir01:$ quilt add backtrace.c
File backtrace.c added to patch 03-bt-delcomments.patch
[root@ubuntu]compdir01:$ quilt refresh
Refreshed patch 03-bt-delcomments.patch
[root@ubuntu]compdir01:$

要回退刚才的改动,使用pop:
[root@ubuntu]compdir01:$ quilt pop
Removing patch 03-bt-delcomments.patch
Restoring backtrace.c
Now at patch 02-bt-addr2name.patch
即现在将03-bt-delcomments.patch撤销了,代码目前处于打上02-bt-addr2name.patch的状态。

如果要撤销所有的patch,则执行

quilt pop -a


对应的,要应用下一个尚未应用的patch的操作为push:
[root@ubuntu]compdir01:$ quilt push

要应用所有可用的patch,则执行

quilt push -a


pop和push都可以指定某个patch,假如现在代码处在最原始的状态:
[root@ubuntu]compdir01:$ quilt push patches/03-bt-delcomments.patch 
Applying patch 00-bt.patch
patching file main.c


Applying patch 02-bt-addr2name.patch
patching file backtrace.c
patching file backtrace.h
patching file main.c


Applying patch 03-bt-delcomments.patch
patching file backtrace.c


Now at patch 03-bt-delcomments.patch
[root@ubuntu]compdir01:$ quilt pop patches/00-bt.patch 
Removing patch 03-bt-delcomments.patch
Restoring backtrace.c


Removing patch 02-bt-addr2name.patch
Restoring backtrace.h
Restoring main.c
Restoring backtrace.c


Now at patch 00-bt.patch
可以看到,quilt会把中间所有需要pop或push的patch都应用上。另外,注意quilt pop patches/00-bt.patch命令效果是回退到打上00-bt.patch的状态,并不回退00-bt.patch本身。

查看已经打上的patch:
[root@ubuntu]compdir01:$ quilt applied
00-bt.patch
02-bt-addr2name.patch
查看尚未应用的patch:
[root@ubuntu]compdir01:$ quilt unapplied
03-bt-delcomments.patch

查看下一个patch:
[root@ubuntu]compdir01:$ quilt next
03-bt-delcomments.patch
查看前一个patch:
[root@ubuntu]compdir01:$ quilt previous
00-bt.patch
查看当前的patch:
[root@ubuntu]compdir01:$ quilt top
02-bt-addr2name.patch

查看当前最新应用的patch关联的文件:
[root@ubuntu]compdir01:$ quilt files
backtrace.c
backtrace.h
main.c
查看所有已应用的patch的关联文件:quilt files -a
也可以指定某个patch:
[root@ubuntu]compdir01:$ quilt files patches/00-bt.patch 
main.c
对应的,查看一个文件所关联的patch(已经应用的patches):
[root@ubuntu]compdir01:$ quilt patches backtrace.c
02-bt-addr2name.patch
03-bt-delcomments.patch

在本地修改文件后,若想撤销修改,则使用revert命令:
[root@ubuntu]compdir01:$ quilt revert main.c
Changes to backtrace.h in patch 02-bt-addr2name.patch reverted

删除某个patch:
[root@ubuntu]compdir03:$ quilt delete patches/02-bt-addr2name.patch 
Removed patch 02-bt-addr2name.patch
这个patch不再在patches/series里面记录,并且pop和push的时候会被略过,如果是它是所有patch中间的某个patch,那在pop或push的时候可能会出错。所以这个命令一般用于删除最顶层的patch。

给一个patch文件重命名:
[root@ubuntu]compdir01:$ quilt rename -P patches/00-bt.patch patches/00-bt-addprint.patch
Patch 00-bt.patch renamed to 00-bt-addprint.patch

编辑一个源文件:
quilt edit file ...
这种修改源文件的方式和不使用quilt edit编辑的区别是,修改的文件同时与当前patch建立关联,不用再执行quilt add建立文件关联了。
如果修改了文件,但不想生成新的patch而是更新原来的patch则直接执行
quilt refresh

查看当前代码和上一个patch的区别:
[root@ubuntu]compdir01:$ quilt diff
会列出当前patch和上一个patch的区别,包括本地未提交的修改。
quilt diff -z则只能看到本地未提交的修改。但是只能看到当前patch关联的那些文件。
例如,如果backtrace.c未关联到当前patch,则即使backtrace.c做了修改也看不到,可以用-P指定关联该文件的最新patch来查看本地修改:
quilt diff -z backtrace.c -P patches/03-bt-delcomments.patch

在patches/目录下的子目录下创建patch文件:
[root@ubuntu]compdir03:$ quilt new pdir/02-dir-order.patch
Patch pdir/02-dir-order.patch is now on top
[root@ubuntu]compdir03:$ quilt add main.c
File main.c added to patch pdir/02-dir-order.patch

发布patch:
只需将patches目录发布即可。当下载了一个原始代码之后,将patches目录拷贝到代码目录,就可以使用了。



你可能感兴趣的:(openwrt,Linux系统)