DEY在开发过程中会持续更新,一般已发现的Bug在下一个版本中会修正。如果您在使用一些比较旧的DEY版本,已经停止新的开发更新,但仍发现一些Bug时,就可以利用研发提供的补丁来修复。这里介绍如何在git下给DEY项目打补丁。

Linux下git的patch功能介绍 Patch(补丁)是一个相当重要的东西,因为几乎所有的大型UNIX项目的普通贡献者,都是通过 Patch来提交代码的。作为最重要的开源项目之一,Linux,也是这样的。普通开发者从软件仓库clone下代码,然后写入代码,做一个Patch, 最后用E-mail发给Linux Kernel的维护者就好了。Git最初作为Linux的版本控制工具,提供了透明、完整、稳定的Patch功能。

Linux下的patch工具可以根据一个diff文件进行版本更新,不过在git中,我们没有必要直接使用diff和patch来做补丁,这样做既危险又麻烦。git提供了两种简单的patch方案。一是用git diff生成的标准patch,二是git format-patch生成的Git专用Patch。

  • git diff生成的标准patch

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

# mkdir test
# cd test
# nano a
This is a file
# git init
# git add a
# git commit
新建个branch 
# git branch Fix
# git checkout Fix
Switched to branch 'Fix'

接下来我们在a文件里面追加一行,然后执行git diff。 (注意我们有修改,为了和该branch版本源文件比较,先不要git add和git commit,这样才能有git diff结果)

# echo 'Fix!!!' >> a
# 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:

# git commit -a -m "Fix"
[Fix b88c46b] Fix
1 files changed, 1 insertions(+), 0 deletions(-)
# git diff master > patch

这样就生成一个patch文件,为该branch和master的diff结果

# git checkout master
Switched to branch 'master'

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

# git branch PATCH
# git checkout PATCH
Switched to branch 'PATCH'
# git apply patch
# 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。

  • git format-patch生成的git 专用补丁

我们同样用上面那个例子的工作目录,这次,我们在Fix分支中的a添加了新行之后,用git format-patch生成一个patch。

# git checkout Fix
# Switched to branch 'Fix'
# echo 'Fix!!!'>>a
# git commit -a -m "Fix1"
[Fix 6991743] Fix1
1 files changed, 1 insertions(+), 0 deletions(-)
# git format-patch -M master
0001-Fix1.patch

上面的学习可以知道,“git commit -a”就是把所有改变都commit,都不需要git add来操作。 git format-patch的-M选项表示这个patch要和那个分支比对。现在它生成了一个patch文件,我们看看那是什么:

# 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来应用。

# git checkout master
Switched to branch 'master'
# git branch PATCH
# git checkout PATCH
# git am 0001-Fix1.patch
Applying: Fix1
# git commit -a -m "PATCH apply"

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

# cat a
This is the file a.
Fix!!!

果然,多了一个Fix!!!

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

提交补丁到邮件列表:

# git send-email --to <maintainer's email> --cc <mailing list>  <your patch>

注意:git send-email在很多机器上没有默认安装,需要进行手动安装

总结一下,利用git format-patch制作补丁大概有以下步骤:1)新建分支 2)在新建的分支上进行相关修改 3)提交修改到本地数据库 4)针对上一个支生成补丁5)另外新建分支,验证补丁6)提交补丁到邮件列表。

两种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生成补丁。

我们可以用上述的方法来直接应用研发提供的patch补丁, 一般您需要在本机或公司内部新建自己的项目git的master分支。把工作目录上的内容提交上去,当有新的patch来时,用上面方法应用到branch,测试稳定才合并到master去,如果不是所有项目都要用,也可以保留这个branch而不合并到master,工作目录则一直从master取数据,并将稳定结果提交。这个方法的好处是多台电脑可以协同,本机调试不易破坏原来代码,并且可以借机自己管理版本库。