Chinaunix首页 | 论坛 | 博客
  • 博客访问: 128776
  • 博文数量: 62
  • 博客积分: 1476
  • 博客等级: 上尉
  • 技术积分: 662
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-03 16:38
文章分类

全部博文(62)

文章存档

2010年(14)

2009年(48)

我的朋友

分类: LINUX

2009-12-03 18:43:00

(材料部分来自社区,但全文属个人整理)

用patch命令应用补丁,当要对单个文件应用补丁,进入文件所在的目录并调用patch命令:

patch < foo.patch

这些命令假定补丁是以统一格式分发的,这种格式指明了补丁要应用到的文件。如果不是,你可以在命令行里指定文件:

patch foo.txt < bar.patch

应用补丁到整个目录(这种情况也许更常见)也是类似的,但是你必须注意设置p级别。就是说,在补丁文件里,需要打补丁的文件在你电脑上的路径名跟 在创建补丁的电脑上可能不同。p级别告诉patch命令忽略掉路径名的几个部分以正确的识别文件。通常p级别为1就够了,所以你使用:

patch -p1 < bar.patch

运行该命令之前,你应该进入源代码目录的顶层目录。如果补丁级别1不能正确识别任何需要打补丁的文件,检查补丁文件里的文件名。如果你看到这样一个文件名:

/users/stephen/package/src/net/http.c

而你当前正工作在一个包含net/http.c的目录,使用:

patch -p5 < bar.patch

总的来说,对于从路径最开始删除的每个路径分隔符(斜线字符)加一,直到剩下的部分存在于你的工作目录中。最后得到的就是p级别。

要删除补丁,用-R参数,例如:

patch -p5 -R bar.patch

使用diff创建补丁

不论是对于单个文件还是整个源码目录,使用diff都很简单。为单个文件创建补丁,用下面形式:

diff -u original.c new.c > original.patch

为整个源码树创建补丁,复制一份源码树:

cp -R original new

在目录new/里进行必要的修改,然后用下面的命令创建补丁:

diff -rupN original/ new/ > original.patch











diff的输出格式分为传统格式和统一格式


1)diff的传统格式输出.
############################################
cat before.txt
输出:
This is a line to be deleted
This is a line that will be changed
This is a line that will be unchanged

cat after.txt
输出:
This is a line that has been changed
This is a line that will be unchanged
This is a line that has been added
############################################
diff before.txt after.txt
输 出:
1,2c1
< This is a line to be deleted
< This is a line that will be changed
---
> This is a line that has been changed
3a3
> This is a line that has been added
############################################

注释:
传统格式的输出
1,2c1是指替换第1个文件的第1,2行到第2个文件的第2行,这里的1,2是指第1个文件的第1,2行,c是替换的意思,最后的1是第2个文件的第1行
<号是指第1个文件更改或删除的行
---号是分割两个文件
>号是第2个文件中增加或删除的行
3a3是指将将第1个文件的第3行,插入到第2个文件的第3行。
也就是说第1个文件的:
< This is a line to be deleted
< This is a line that will be changed
被替换成第2个文件的:
> This is a line that has been changed
由于第1个文件的第3行和第2个文件的第2行一致,所以不做修改.
由于第2个文件的第3行是第1个文件所不具有的,所以在第1个文件的最后一行增加:
> This is a line that has been added





2)patch命令的应用

用diff的传统格式输出:
############################################
diff before.txt after.txt >mypatch.txt
############################################

用patch修补before.txt文件,使before.txt和after.txt一致.
############################################
cat mypatch.txt |patch before.txt
输出:
patching file before.txt
############################################

比较两个文件,现在是一致的了.
############################################
cmp before.txt after.txt
############################################

用patch命令恢复before.txt.
############################################
patch -R before.txt 输出:
patching file before.txt
############################################

注:-R标记告诉patch在反向上应用区别或者撤销patch.

再比较两个文件,现在不一致了.
############################################
cmp before.txt after.txt
输出:
before.txt after.txt differ: byte 17, line 1
############################################




3)diff的统一格式输出.
############################################
cat before.txt
输出:
This is a line to be deleted
This is a line that will be changed
This is a line that will be unchanged

cat after.txt
输出:
This is a line that has been changed
This is a line that will be unchanged
This is a line that has been added
############################################
############################################
diff -u before.txt after.txt |tee mypatch.diff
输出:
--- before.txt 2009-06-20 05:21:49.000000000 +0800
+++ after.txt 2009-06-20 04:03:16.000000000 +0800
@@ -1,3 +1,3 @@
-This is a line to be deleted
-This is a line that will be changed
+This is a line that has been changed
This is a line that will be unchanged
+This is a line that has been added
############################################

注释:
diff -u选项是统一格式输出.
--- before.txt 2009-06-20 05:21:49.000000000 +0800
--- before.txt是指旧文件
+++ after.txt 2009-06-20 04:03:16.000000000 +0800
+++ after.txt 是指新文件.
@@ -1,3 +1,3 @@
@@ -1,3中的-1指原始文件(-)起始行号(1),3指该块在原始文件共有3行,+1,3 @@中的+1指目标文件(+)的块起始行(1),经Patch后的块共有3行.
-This is a line to be deleted
-This is a line that will be changed
是被删除的行
+This is a line that has been changed
是增加的行
This is a line that will be unchanged
没有-号和+号是指该行不变,因为after.txt和before.txt都有这行.
+This is a line that has been added
是增加的行
diff的统一格式比较与输出是按顺序进行的.




4)diff命令在目录中的应用.

新建old和new目录,old目录包含了初始内容,new目录包含文件的最新版本.
#####################################################
mkdir old new
echo "This is one. It's unchanged." | tee old/one new/one
echo "This is two. It will change." > old/two
echo "This is two. It changed.">new/two
echo "This is three. It's new." > new/three
#####################################################

创建修补文件
#####################################################
diff -Nur old/ new/ >mypatch.diff
#####################################################
注:-r选项按照文件目录递归创建修补文件.
-u指统一模式
-N是指当diff遇到一个只存在于两个树中的一个树中的文件时,默认情况下跳过文件并且打印一个警告到stderr.
这个行为可以通过-N选项来更改,这也导致了diff认为丢失的文件实际上是存在的,但它是空的.采用这种方式,
一个修补文件可以包括已经创建的文件.然后应用修补程序创建新的文件.

#####################################################
more mypatch.diff
输出:
diff -Nur old/three new/three
--- old/three 1970-01-01 08:00:00.000000000 +0800
+++ new/three 2009-06-20 06:55:34.000000000 +0800
@@ -0,0 +1 @@
+This is three. It's new.
diff -Nur old/two new/two
--- old/two 2009-06-20 06:55:08.000000000 +0800
+++ new/two 2009-06-20 06:55:21.000000000 +0800
@@ -1 +1 @@
-This is two. It will change.
+This is two. It changed.
#####################################################
注释:
diff -Nur old/three new/three是指下面比较old/three new/three两个文件.
因为没有old/three文件,所以在old/three中增加+This is three. It's new.
diff -Nur old/two new/two是指下面比较old/two new/two两个文件
因为old/two与new/two的第3行不一致,所以删除This is two. It will change.增加This is two. It changed.


打补丁到old目录,新建old/three以及更改old/two
#####################################################
patch --dir old< mypatch.diff
ls -l old/
输出:
one three two
#####################################################

恢复old目录的内容,包括删除old/three,以及恢复old/two文件
#####################################################
patch --dir old -R 输出:
ls -l old/
one two
#####################################################



5)检查和合并更改

用vim突出显示单个字符的更改来表示区别.

#####################################################
vim -d after.txt before.txt
#####################################################


用gui工具gvimdiff来显示两个文件.

#####################################################
gvimdiff after.txt before.txt
#####################################################


新建文件orig.c

#####################################################
vi orig.c
void foo(void)
{
printf("This will be changed by me. \n");

printf("This will be unchanged,\n");

printf("This will be changed by you.\n");
}
#####################################################


复制文件orig.c到me.c,更改第4行为printf("This was changed by me. \n");
#####################################################
vi me.c
void foo(void)
{
printf("This was changed by me. \n");

printf("This will be unchanged,\n");

printf("This will be changed by you.\n");
}
#####################################################


复制文件orig.c到you.c,更改第7行为printf("This was changed by you.\n");
#####################################################
vi you.c
void foo(void)
{
printf("This will be changed by me. \n");

printf("This will be unchanged,\n");

printf("This was changed by you.\n");
}
#####################################################

版本工具如cvs,subversion使用GNU合并工具称为diff3.
#####################################################
diff3 me.c orig.c you.c
输出:
====1
1:3c
printf("This was changed by me. \n");
2:3c
3:3c
printf("This will be changed by me. \n");
====3
1:7c
2:7c
printf("This will be changed by you.\n");
3:7c
printf("This was changed by you.\n");

注:
在没有参数的情况下,diff3产生的输出说明了那行更改.
====1和====3指明造成同原始文件不同的是哪一个修改文件.
编号方式基于参数序列.
也就是第1个文件和第3个文件与原文件不同.
1:3c
printf("This was changed by me. \n");
3:3c
printf("This will be changed by me. \n");
1:3c表示第1个文件的第3行与3:3c表示的第3个文件的第3行不同.
为什么不显示与原文件的比较呢。因为第3个文件的第3行与源文件(第2个文件)相同.所以与哪个文件比较无所谓了.

2:7c
printf("This will be changed by you.\n");
3:7c
printf("This was changed by you.\n");
2:7c表示第2个文件的第7行与3:7c表示的第3个文件的第7行不同.


diff3会试图为我们进行合并.合并是在源文件的基础上,依据两个新文件进行修改
源文件是第二个文件,第一个文件和第三个文件可以互换,但他们必须有共同的祖先,就是第二个文件.

##################################################
diff3 -m me.c orig.c you.c |cat -n
输出:
1 void foo(void)
2 {
3 printf("This was changed by me. \n");
4
5 printf("This will be unchanged,\n");
6
7 printf("This was changed by you.\n");
8 }
###################################################


为了测试更复杂的环境,新建一个文件orig.c.1
内容如下:
###################################################
vi orig.c.1
void foo(void)
{
printf("This will be changed by both of us.\n");
}
###################################################


用diff3 -m再次比较输出,如下:
###################################################
diff3 -m me.c orig.c.1 you.c
void foo(void)
{
<<<<<<< me.c
printf("This was changed by me. \n");

printf("This will be unchanged,\n");

printf("This will be changed by you.\n");
||||||| orig.c.1
printf("This will be changed by both of us.\n");
=======
printf("This will be changed by me. \n");

printf("This will be unchanged,\n");

printf("This was changed by you.\n");
>>>>>>> you.c
}
###################################################

注释:以上的格式,同cvs/svn update,需要人工合并文件的格式是一致的.(材料部分来自社区,但全文属个人整理)

用patch命令应用补丁,当要对单个文件应用补丁,进入文件所在的目录并调用patch命令:

patch < foo.patch

这些命令假定补丁是以统一格式分发的,这种格式指明了补丁要应用到的文件。如果不是,你可以在命令行里指定文件:

patch foo.txt < bar.patch

应用补丁到整个目录(这种情况也许更常见)也是类似的,但是你必须注意设置p级别。就是说,在补丁文件里,需要打补丁的文件在你电脑上的路径名跟 在创建补丁的电脑上可能不同。p级别告诉patch命令忽略掉路径名的几个部分以正确的识别文件。通常p级别为1就够了,所以你使用:

patch -p1 < bar.patch

运行该命令之前,你应该进入源代码目录的顶层目录。如果补丁级别1不能正确识别任何需要打补丁的文件,检查补丁文件里的文件名。如果你看到这样一个文件名:

/users/stephen/package/src/net/http.c

而你当前正工作在一个包含net/http.c的目录,使用:

patch -p5 < bar.patch

总的来说,对于从路径最开始删除的每个路径分隔符(斜线字符)加一,直到剩下的部分存在于你的工作目录中。最后得到的就是p级别。

要删除补丁,用-R参数,例如:

patch -p5 -R bar.patch

使用diff创建补丁

不论是对于单个文件还是整个源码目录,使用diff都很简单。为单个文件创建补丁,用下面形式:

diff -u original.c new.c > original.patch

为整个源码树创建补丁,复制一份源码树:

cp -R original new

在目录new/里进行必要的修改,然后用下面的命令创建补丁:

diff -rupN original/ new/ > original.patch











diff的输出格式分为传统格式和统一格式


1)diff的传统格式输出.
############################################
cat before.txt
输出:
This is a line to be deleted
This is a line that will be changed
This is a line that will be unchanged

cat after.txt
输出:
This is a line that has been changed
This is a line that will be unchanged
This is a line that has been added
############################################
diff before.txt after.txt
输 出:
1,2c1
< This is a line to be deleted
< This is a line that will be changed
---
> This is a line that has been changed
3a3
> This is a line that has been added
############################################

注释:
传统格式的输出
1,2c1是指替换第1个文件的第1,2行到第2个文件的第2行,这里的1,2是指第1个文件的第1,2行,c是替换的意思,最后的1是第2个文件的第1行
<号是指第1个文件更改或删除的行
---号是分割两个文件
>号是第2个文件中增加或删除的行
3a3是指将将第1个文件的第3行,插入到第2个文件的第3行。
也就是说第1个文件的:
< This is a line to be deleted
< This is a line that will be changed
被替换成第2个文件的:
> This is a line that has been changed
由于第1个文件的第3行和第2个文件的第2行一致,所以不做修改.
由于第2个文件的第3行是第1个文件所不具有的,所以在第1个文件的最后一行增加:
> This is a line that has been added





2)patch命令的应用

用diff的传统格式输出:
############################################
diff before.txt after.txt >mypatch.txt
############################################

用patch修补before.txt文件,使before.txt和after.txt一致.
############################################
cat mypatch.txt |patch before.txt
输出:
patching file before.txt
############################################

比较两个文件,现在是一致的了.
############################################
cmp before.txt after.txt
############################################

用patch命令恢复before.txt.
############################################
patch -R before.txt 输出:
patching file before.txt
############################################

注:-R标记告诉patch在反向上应用区别或者撤销patch.

再比较两个文件,现在不一致了.
############################################
cmp before.txt after.txt
输出:
before.txt after.txt differ: byte 17, line 1
############################################




3)diff的统一格式输出.
############################################
cat before.txt
输出:
This is a line to be deleted
This is a line that will be changed
This is a line that will be unchanged

cat after.txt
输出:
This is a line that has been changed
This is a line that will be unchanged
This is a line that has been added
############################################
############################################
diff -u before.txt after.txt |tee mypatch.diff
输出:
--- before.txt 2009-06-20 05:21:49.000000000 +0800
+++ after.txt 2009-06-20 04:03:16.000000000 +0800
@@ -1,3 +1,3 @@
-This is a line to be deleted
-This is a line that will be changed
+This is a line that has been changed
This is a line that will be unchanged
+This is a line that has been added
############################################

注释:
diff -u选项是统一格式输出.
--- before.txt 2009-06-20 05:21:49.000000000 +0800
--- before.txt是指旧文件
+++ after.txt 2009-06-20 04:03:16.000000000 +0800
+++ after.txt 是指新文件.
@@ -1,3 +1,3 @@
@@ -1,3中的-1指原始文件(-)起始行号(1),3指该块在原始文件共有3行,+1,3 @@中的+1指目标文件(+)的块起始行(1),经Patch后的块共有3行.
-This is a line to be deleted
-This is a line that will be changed
是被删除的行
+This is a line that has been changed
是增加的行
This is a line that will be unchanged
没有-号和+号是指该行不变,因为after.txt和before.txt都有这行.
+This is a line that has been added
是增加的行
diff的统一格式比较与输出是按顺序进行的.




4)diff命令在目录中的应用.

新建old和new目录,old目录包含了初始内容,new目录包含文件的最新版本.
#####################################################
mkdir old new
echo "This is one. It's unchanged." | tee old/one new/one
echo "This is two. It will change." > old/two
echo "This is two. It changed.">new/two
echo "This is three. It's new." > new/three
#####################################################

创建修补文件
#####################################################
diff -Nur old/ new/ >mypatch.diff
#####################################################
注:-r选项按照文件目录递归创建修补文件.
-u指统一模式
-N是指当diff遇到一个只存在于两个树中的一个树中的文件时,默认情况下跳过文件并且打印一个警告到stderr.
这个行为可以通过-N选项来更改,这也导致了diff认为丢失的文件实际上是存在的,但它是空的.采用这种方式,
一个修补文件可以包括已经创建的文件.然后应用修补程序创建新的文件.

#####################################################
more mypatch.diff
输出:
diff -Nur old/three new/three
--- old/three 1970-01-01 08:00:00.000000000 +0800
+++ new/three 2009-06-20 06:55:34.000000000 +0800
@@ -0,0 +1 @@
+This is three. It's new.
diff -Nur old/two new/two
--- old/two 2009-06-20 06:55:08.000000000 +0800
+++ new/two 2009-06-20 06:55:21.000000000 +0800
@@ -1 +1 @@
-This is two. It will change.
+This is two. It changed.
#####################################################
注释:
diff -Nur old/three new/three是指下面比较old/three new/three两个文件.
因为没有old/three文件,所以在old/three中增加+This is three. It's new.
diff -Nur old/two new/two是指下面比较old/two new/two两个文件
因为old/two与new/two的第3行不一致,所以删除This is two. It will change.增加This is two. It changed.


打补丁到old目录,新建old/three以及更改old/two
#####################################################
patch --dir old< mypatch.diff
ls -l old/
输出:
one three two
#####################################################

恢复old目录的内容,包括删除old/three,以及恢复old/two文件
#####################################################
patch --dir old -R 输出:
ls -l old/
one two
#####################################################



5)检查和合并更改

用vim突出显示单个字符的更改来表示区别.

#####################################################
vim -d after.txt before.txt
#####################################################


用gui工具gvimdiff来显示两个文件.

#####################################################
gvimdiff after.txt before.txt
#####################################################


新建文件orig.c

#####################################################
vi orig.c
void foo(void)
{
printf("This will be changed by me. \n");

printf("This will be unchanged,\n");

printf("This will be changed by you.\n");
}
#####################################################


复制文件orig.c到me.c,更改第4行为printf("This was changed by me. \n");
#####################################################
vi me.c
void foo(void)
{
printf("This was changed by me. \n");

printf("This will be unchanged,\n");

printf("This will be changed by you.\n");
}
#####################################################


复制文件orig.c到you.c,更改第7行为printf("This was changed by you.\n");
#####################################################
vi you.c
void foo(void)
{
printf("This will be changed by me. \n");

printf("This will be unchanged,\n");

printf("This was changed by you.\n");
}
#####################################################

版本工具如cvs,subversion使用GNU合并工具称为diff3.
#####################################################
diff3 me.c orig.c you.c
输出:
====1
1:3c
printf("This was changed by me. \n");
2:3c
3:3c
printf("This will be changed by me. \n");
====3
1:7c
2:7c
printf("This will be changed by you.\n");
3:7c
printf("This was changed by you.\n");

注:
在没有参数的情况下,diff3产生的输出说明了那行更改.
====1和====3指明造成同原始文件不同的是哪一个修改文件.
编号方式基于参数序列.
也就是第1个文件和第3个文件与原文件不同.
1:3c
printf("This was changed by me. \n");
3:3c
printf("This will be changed by me. \n");
1:3c表示第1个文件的第3行与3:3c表示的第3个文件的第3行不同.
为什么不显示与原文件的比较呢。因为第3个文件的第3行与源文件(第2个文件)相同.所以与哪个文件比较无所谓了.

2:7c
printf("This will be changed by you.\n");
3:7c
printf("This was changed by you.\n");
2:7c表示第2个文件的第7行与3:7c表示的第3个文件的第7行不同.


diff3会试图为我们进行合并.合并是在源文件的基础上,依据两个新文件进行修改
源文件是第二个文件,第一个文件和第三个文件可以互换,但他们必须有共同的祖先,就是第二个文件.

##################################################
diff3 -m me.c orig.c you.c |cat -n
输出:
1 void foo(void)
2 {
3 printf("This was changed by me. \n");
4
5 printf("This will be unchanged,\n");
6
7 printf("This was changed by you.\n");
8 }
###################################################


为了测试更复杂的环境,新建一个文件orig.c.1
内容如下:
###################################################
vi orig.c.1
void foo(void)
{
printf("This will be changed by both of us.\n");
}
###################################################


用diff3 -m再次比较输出,如下:
###################################################
diff3 -m me.c orig.c.1 you.c
void foo(void)
{
<<<<<<< me.c
printf("This was changed by me. \n");

printf("This will be unchanged,\n");

printf("This will be changed by you.\n");
||||||| orig.c.1
printf("This will be changed by both of us.\n");
=======
printf("This will be changed by me. \n");

printf("This will be unchanged,\n");

printf("This was changed by you.\n");
>>>>>>> you.c
}
###################################################

注释:以上的格式,同cvs/svn update,需要人工合并文件的格式是一致的.

阅读(2177) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

zyqhi2013-05-07 14:59:34

太长了啊~~~~