Git patch

来源:互联网 发布:js的面向对象 编辑:程序博客网 时间:2024/05/16 11:50

http://blog.csdn.net/flyingqr/article/details/6656862

打patch:

git-format-patch x..y

x y 是哈希值,从x到y依次打patch

如果只是生成一个commit的patch,可以用git-format-patch -1 commit

如果想从历史头开始commit 用 git-format-patch --root commit

 

里面包含了提交的日志,作者,日期等信息。你想做的是把这些patch引入到你的
代码库中,最好是也可以把日志也引入进来, 方便以后维护用。传统的打patch方式是

patch -p1 < 0001--JFFS2-community-fix-with-not-use-OOB.patch

这样来打patch,但是这样会把这些有用的信息丢失。

由于这些patch显然是用git format-patch来生成的,所以用git的工具应该就可以很好的做好。

git-am 就是作这件事情。

在使用git-am之前, 你要首先git am –abort 一次,来放弃掉以前的am信息,这样才可以进行一次全新的am。
不然会遇到这样的错误。
.git/rebase-apply still exists but mbox given.

git-am 可以一次合并一个文件,或者一个目录下所有的patch,或者你的邮箱目录下的patch.

下面举两个例子:

  1. 你现在有一个code base: small-src, 你的patch文件放在~/patch/0001-trival-patch.patch

cd small-srcgit-am ~/patch/0001-trival-patch.patch

如果成功patch上去, 你就可以去喝杯茶了。

如果失败了, git 会提示错误, 比如:

error: patch failed: android/mediascanner.cpp:452error: android/mediascanner.cpp: patch does not apply

这样你就需要先看看patch, 然后改改错误的这个文件,让这个patch能够patch上去。

  1. 你有一堆patch, 名字是上面提到的那一堆patch, 你把他们放在~/patch-set/目录下(路径随意)

cd opencoregit am ~/patch-set/*.patch

(这里git就会按照文件名的顺序一次am这些patch)
如果一切顺利, 你所有的patch都OK了, 你又Lucky了。

不过不顺利的时候十有八九,如果git am中间遇到了patch,am就会停到打这个
patch的地方, 告诉你是哪个patch打不上去。

比如我现在有一个文件file,有两个patch.
file 的内容是

the textmore text

两个patch分别是:

0001-add-line.patch:

From 48869ccbced494e05738090afa5a54f2a261df0f Mon Sep 17 00:00:00 2001From: zhangjiejing <zhangjiejing@zhangjiejing-desktop.(none)>Date: Thu, 22 Apr 2010 13:04:34 +0800Subject: [PATCH 1/2] add line--- file |    2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)diff --git a/file b/fileindex 067780e..685f0fa 100644--- a/file+++ b/file@@ -3,3 +3,5 @@ file: some text more text++add line--1.6.3.3

0002-change-line.patch:

From f756e1b3a87c216b7e0afea9d15badd033171578 Mon Sep 17 00:00:00 2001From: zhangjiejing <zhangjiejing@zhangjiejing-desktop.(none)>Date: Thu, 22 Apr 2010 13:05:19 +0800Subject: [PATCH 2/2] change line--- file |    2 +- 1 files changed, 1 insertions(+), 1 deletions(-)diff --git a/file b/fileindex 685f0fa..7af7852 100644--- a/file+++ b/file@@ -1,6 +1,6 @@ file:-some text+Change line text more text--1.6.3.3

运行
git am *.patch

来merge这些patch, 报错, Patch failed at 0001 add line这样我们看0001这
个patch,原来patch需要的是some text, 而file里面是the text, 所以我们用编
辑器把这行改成some text,

vi filegit apply 0001-add-line.patchgit add filegit am --resolved

在解决完冲突以后, 比如用git add来让git知道你已经解决完冲突了。

  • 如果你发现这个冲突是无法解决的, 要撤销整个am的东西。 可以运行git am –abort,
  • 如果你想只是忽略这一个patch,可以运行git am –skip来跳过这个patch.
http://sweetdum.com/wordpress/?p=153

在git中,我们没有必要直接使用diff和patch来做补丁,这样做既危险又麻烦。git提供了两种简单的patch方案。一是用git diff生成的标准patch,二是git format-patch生成的Git专用Patch。

1.git diff生成的标准patch

我们可以首先用git diff制作一个patch。本文示例的工作目录里最初有一个文件a,内容是“This is the file a.”,放置在master分支中。为了修改代码,我们一般的做法是建立一个新分支:

sweetdum@sweetdum-ASUS:~/GitEx$ git branch Fix
sweetdum@sweetdum-ASUS:~/GitEx$ git checkout Fix
Switched to branch 'Fix'

接下来我们在a文件里面追加一行,然后执行git diff。
sweetdum@sweetdum-ASUS:~/GitEx$ echo 'Fix!!!'>>a
sweetdum@sweetdum-ASUS:~/GitEx$ git diff
diff --git a/a b/a
index 4add65f..0d295ac 100644
--- a/a
+++ b/a
@@ -1 +1,2 @@
This is the file a.
+Fix!!!

我们看到了Git diff的输出,这是一个非常典型的Patch式diff。这样我们可以直接把这个输出变为一个Patch:
sweetdum@sweetdum-ASUS:~/GitEx$ git commit -a -m "Fix"
[Fix b88c46b] Fix
1 files changed, 1 insertions(+), 0 deletions(-)
sweetdum@sweetdum-ASUS:~/GitEx$ git diff master > patch
sweetdum@sweetdum-ASUS:~/GitEx$ git checkout master
Switched to branch 'master'

我们现在有一个patch文件,并且签出了master,接下来我们可以使用git apply来应用这个patch。当然了,实际应用中,我们不会这样在一个分支建patch,到另一个分支去应用,因为只有merge一下就好了。我们现 在权当没有这个Fix分支。一般情况下,为了保护master,我们会建立一个专门处理新交来的patch的分支:

sweetdum@sweetdum-ASUS:~/GitEx$ git branch PATCH
sweetdum@sweetdum-ASUS:~/GitEx$ git checkout PATCH
Switched to branch 'PATCH'
sweetdum@sweetdum-ASUS:~/GitEx$ git apply patch
sweetdum@sweetdum-ASUS:~/GitEx$ git commit -a -m "Patch Apply"
[PATCH 9740af8] Patch Apply
1 files changed, 1 insertions(+), 0 deletions(-)

看,现在我们在PATCH分支中应用了这个补丁,我们可以把PATCH分支和Fix比对一下,结果肯定是什么也没有,说明PATCH分支和Fix分支完全一样。patch应用成功。即使有多个文件git diff 也能生成一个patch。

2.git format-patch生成的git专用补丁。

我们同样用上面那个例子的工作目录,这次,我们在Fix分支中的a添加了新行之后,用git format-patch生成一个patch。
sweetdum@sweetdum-ASUS:~/GitEx$ git checkout Fix
Switched to branch 'Fix'
sweetdum@sweetdum-ASUS:~/GitEx$ echo 'Fix!!!'>>a
sweetdum@sweetdum-ASUS:~/GitEx$ git commit -a -m "Fix1"
[Fix 6991743] Fix1
1 files changed, 1 insertions(+), 0 deletions(-)
sweetdum@sweetdum-ASUS:~/GitEx$ git format-patch -M master
0001-Fix1.patch

git format-patch的-M选项表示这个patch要和那个分支比对。现在它生成了一个patch文件,我们看看那是什么:

sweetdum@sweetdum-ASUS:~/GitEx$ cat 0001-Fix1.patch
From 6991743354857c9a6909a253e859e886165b0d90 Mon Sep 17 00:00:00 2001
From: Sweetdumplings <linmx0130@163.com>
Date: Mon, 29 Aug 2011 14:06:12 +0800
Subject: [PATCH] Fix1

---
a |    1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/a b/a
index 4add65f..0d295ac 100644
--- a/a
+++ b/a
@@ -1 +1,2 @@
This is the file a.
+Fix!!!
--
1.7.4.1

看,这次多了好多东西,不仅有diff的信息,还有提交者,时间等等,仔细一看你会发现,这是个E-mail的文件,你可以直接发送它!这种patch,我们要用git am来应用。

sweetdum@sweetdum-ASUS:~/GitEx$ git checkout master
Switched to branch 'master'
sweetdum@sweetdum-ASUS:~/GitEx$ git branch PATCH
sweetdum@sweetdum-ASUS:~/GitEx$ git checkout PATCH
sweetdum@sweetdum-ASUS:~/GitEx$ git am 0001-Fix1.patch
Applying: Fix1
sweetdum@sweetdum-ASUS:~/GitEx$ git commit -a -m "PATCH apply"

在提交了补丁之后,我们可以再看看目前文件a的情况:

sweetdum@sweetdum-ASUS:~/GitEx$ cat a
This is the file a.
Fix!!!

果然,多了一个Fix!!!

不过要注意的是,如果master与Fix分支中间有多次提交,它会针对每次提交生成一个patch。

3.两种patch的比较:

  • 兼容性:很明显,git diff生成的Patch兼容性强。如果你在修改的代码的官方版本库不是Git管理的版本库,那么你必须使用git diff生成的patch才能让你的代码被项目的维护人接受。
  • 除错功能:对于git diff生成的patch,你可以用git apply --check 查看补丁是否能够干净顺利地应用到当前分支中;如果git format-patch 生成的补丁不能打到当前分支,git am会给出提示,并协助你完成打补丁工作,你也可以使用git am -3进行三方合并,详细的做法可以参考git手册或者《Progit》。从这一点上看,两者除错功能都很强。
  • 版本库信息:由于git format-patch生成的补丁中含有这个补丁开发者的名字,因此在应用补丁时,这个名字会被记录进版本库,显然,这样做是恰当的。因此,目前使用Git的开源社区往往建议大家使用format-patch生成补丁。