转自: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。

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

Git的Patch功能的更多相关文章

  1. git diff patch方法

    UNIX世界的软件开发大多都是协作式的,因此,Patch(补丁)是一个相当重要的东西,因为几乎所有的大型UNIX项目的普通贡献者,都是通过 Patch来提交代码的.作为最重要的开源项目之一,Linux ...

  2. git diff 生成patch, git apply patch 打补丁方法说明,以及分支管理的简单操作。

    git diff 简易操作说明 先git log 查看commit ID, 记录你想要打的补丁的ID 比如说: git log commit 4ff35d800fa62123a28b7bda2a04e ...

  3. git 生成patch 和打入patch

    转载:https://blog.csdn.net/liuhaomatou/article/details/54410361 平时我们在使用git 管理项目的时候,会遇到这样一种情况,那就是客户使用gi ...

  4. 如何使用git 生成patch 和打入patch【转】

    本文转载自:http://blog.csdn.net/liuhaomatou/article/details/54410361 平时我们在使用git 管理项目的时候,会遇到这样一种情况,那就是客户使用 ...

  5. 如何使用git 生成patch 和打入patch 标签: gitpatch【转】

    本文转载自:http://blog.csdn.net/liuhaomatou/article/details/54410361 平时我们在使用git 管理项目的时候,会遇到这样一种情况,那就是客户使用 ...

  6. [Git] Use git add --patch for better commit history and mitigating bugs

    Let's split our changes into separate commits. We'll be able to check over our changes before stagin ...

  7. 使用git的分支功能实现定制功能摘取与组合的想法

    前言,这个想法应该是git比较通用的做法,只是我还没用过,所以把自己的想法记录在这里,督促自己以后按这个方式执行. 我们公司现在面临一个问题, 就是客户的定制需求很多,很杂,其中坑爹需求很多. 我还没 ...

  8. git diff patch

    如何生成patch:修改一个地方,然后git diff > xxx.patch 就会生成一个patch文件,这里的关键似乎是, 源文件的某个模块的版本要和线上发布的最新版本要一致,这样patch ...

  9. [git] git 的基础功能

    有两种方法获得一个 git 仓库:自行初始化,克隆别人已有的仓库 自行初始化 git init 克隆别人已有的库 git clone git@github.com:garrisonz/gitStudy ...

随机推荐

  1. Java编程里类的继承

    今天,我们将要讨论的内容是Java里面类的继承的相关概念. 说到继承,我相信大家都不陌生.生活中,子承父业,子女继承父母的财产,这就是继承.实际上,Java里的继承也是如此.对于一个类来说,它的数据成 ...

  2. 从零开始学 Java - Windows 下安装 Eclipse

    三观是什么鬼 当我们在讨论「三观一致」的时候是在讨论些什么? 我认为这个世界上本没有「三观」这一说法,说的人多了,也就有了「三观」这个词,当我们讨论「三观一致」其实并不是真的在说世界观.价值观.人生观 ...

  3. 一个过滤特殊字符的JS

    <script language="javascript"> function checkForms() { var iu, iuu, regArray=new Arr ...

  4. Mvc视图的那些事

    最近参与项目底层重写,在代码组织方式,类型使用上已经与之前有了很大的不同,这里总结一下视图的使用. 一.视图中命名空间的使用 视图命名空间的使用方式大致有三种:一,完全限定名,如 @System.Da ...

  5. javascript中concat方法深入理解

    最近在恶补js知识的时候,总是会因为js强大的语法而感到震撼.因为以前对前端方面的疏忽,导致了一些理解的错误.因此痛改前非,下定决心,不管做什么事情,都要有专研的精神. 在介绍前,抛出一个问题:如何将 ...

  6. angular源码分析:angular中入境检察官$sce

    一.ng-bing-html指令问题 需求:我需要将一个变量$scope.x = '<a href="http://www.cnblogs.com/web2-developer/&qu ...

  7. JavaScript toUpperCase() 方法和 toLowerCase() 方法

    1,toUpperCase() 方法用于把字符串转换为大写. 一个新的字符串,在其中 stringObject 的所有小写字符全部被转换为了大写字符. 语法为: stringObject.toUppe ...

  8. JS特效之Tab标签切换

    在我们平时浏览网站的时候,经常看到的特效有图片轮播.导航子菜单的隐藏.tab标签的切换等等.这段时间学习了JS后,开始要写出一些简单的特效.今天我也分享一个简单tab标签切换的例子.先附上代码: HT ...

  9. Imperva WAF使用笔记

    添加IP白名单 在对自己公司网站进行安全测试时会被WAF拦截,如果把WAF彻底停掉就无法拦截到外部的攻击了. 此时可以添加IP地址白名单,白名单内的IP对网站发起扫描时不会做拦截.

  10. android常犯错误记录

    错误:Error:Error: Found item Attr/border_width more than one time 这个容易,属性相同了,按照提示查询一下找出来删了就行了,注意大小写很容易 ...