转自: http://smilejay.com/2012/08/generate-a-patch-from-a-commit/
在看一个Bugzilla上Xen的一个bug时,提到要revert掉Dom0(用linux.git)中一个commit,当然git是有revert命令的,如下所示。
1 2 3 4 5 |
[root@jay-linux linux.git]# git revert cd9db80e5257682a7f7ab245a2459648b3c8d268 warning: too many files (created: 2321 deleted: 1460), skipping inexact rename detection Finished one revert. [detached HEAD aab6b2f] Revert "xen/pciback: Support pci_reset_function, aka FLR or D3 support." 2 files changed, 3 insertions(+), 39 deletions(-) |
(BTW,由于那个commit后的改动太多,可能会导致直接revert掉后不能编译成功(或功能不正常);所以如果真正revert一个commit后要提交时,要做好评估。)
然后,我想看一下这个commit的patch是怎么样的,做了哪些改动,就需要Git根据一个commit SHA-1值生成一个patch,可以使用如下两种方式。
1. git format-patch -1 commit :生成的patch有统计信息和git的版本信息
2. git diff commit_previous commit > mypatch.diff :最原始的diff信息,对于这里的commit_previous(commit之前一个commit),可以使用“commit^”来表示,这样比较方便,不易出错。
实际命令演示如下:
1 2 3 4 5 |
[root@jay-linux linux.git]# git format-patch -1 cd9db80e5257682a7f7ab245a2459648b3c8d268 0001-xen-pciback-Support-pci_reset_function-aka-FLR-or-D3.patch (前部有统计信息;结尾有“--1.7.1”这样的git版本标志。) [root@jay-linux linux.git]# git diff cd9db80e525^ cd9db80e525 > diff.patch |
在commit SHA-1值不重复(冲突)的情况下,可以只写前面几位字符即可(如上面的git diff命令中那样使用)。
第一种方式,除了最重要最基本的diff信息之外,还有如下信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
From a8d30220510cb1d8eac18746570cb52214ac65d7 Mon Sep 17 00:00:00 2001 From: Jay <smile665@gmail.com> Date: Tue, 19 Jun 2012 11:07:02 +0800 Subject: [PATCH] move libvirt config files to a dedicated directory --- config/libvirt/hotplug.xml | 5 ++ config/libvirt/rhel6u3_virsh.xml | 72 ++++++++++++++++++++++++++++++++++ config/libvirt/win8_virsh.xml | 80 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 0 deletions(-) create mode 100644 config/libvirt/hotplug.xml create mode 100644 config/libvirt/rhel6u3_virsh.xml create mode 100644 config/libvirt/win8_virsh.xml (中间是基本diff的信息) diff --git a/config/libvirt/hotplug.xml b/config/libvirt/hotplug.xml new file mode 100644 index 0000000..dc85c22 (最后的git版本信息) -- 1.7.1 |
更多信息,可以:man git-format-patch 和 man git-diff
http://www.cnblogs.com/y041039/articles/2411600.html
UNIX世界的软件开发大多都是协作式的,因此,Patch(补丁)是一个相当重要的东西,因为几乎所有的大型UNIX项目的普通贡献者,都是通过 Patch来提交代码的。作为最重要的开源项目之一,Linux,也是这样的。普通开发者从软件仓库clone下代码,然后写入代码,做一个Patch, 最后用E-mail发给Linux Kernel的维护者就好了。Git最初作为Linux的版本控制工具,提供了透明、完整、稳定的Patch功能。
我们先介绍一下Patch是什么。如果一个软件有了新版本,我们可以完整地下载新版本的代码进行编译安装。然而,像Linux Kernel这样的大型项目,代码即使压缩,也超过70MB,每次全新下载是有相当大的代价的。然而,每次更新变动的代码可能不超过1MB,因此,我们只 要能够有两个版本代码的diff的数据,应该就可以以极低的代价更新程序了。因此,Larry Wall开发了一个工具:patch。它可以根据一个diff文件进行版本更新。
不过在git中,我们没有必要直接使用diff和patch来做补丁,这样做既危险又麻烦。git提供了两种简单的patch方案。一是用git diff生成的标准patch,二是git format-patch生成的Git专用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。
我们同样用上面那个例子的工作目录,这次,我们在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 <[email protected]>
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。