git diff,git format-patch,git apply和patch小问题三则

本文介绍了Git中关于patch的几种常用命令及其应用场景,包括git diff、git format-patch、git apply和git am等命令的使用方法及注意事项。

 

这个文档主要是用来记录工作中遇到的git patch 相关的命令的介绍和相关常见问题的解决方案.

 

Patch文件有3中,git 给我们提供了2种patch 方案, 一是用git diff生成的标准patch,二是git format-patch生成的Git专用Patch。Linux 本身也有一个patch命令.

git diff

使用git diff 来输出2个commit 之前的不同之处来生成patch.


生成的这个patch文件就是我们修改的内容

 

git format-patch

1.将最新的一条修改记录生成patch

 

使用git format-patch生成的patch在文件的前面会有diff的信息,还有提交者,时间等等,仔细一看你会发现,这是个E-mail的文件,你可以直接发送它!这种patch,我们要用git am来应用。

如何直接把其他仓库的修改记录直接合入到当前仓库

例子:

git --git-dir=/home/builder2010/work/6589kk/ALPS.KK1.MP5.V1.3_EASTAEON89_WET_KK/.git format-patch -k -1 --stdout 57b1ace1| git am -3 -k

Git diff 和 git format-patch的对比.

A.兼容性:很明显,git diff生成的Patch兼容性强。如果你在修改的代码的官方版本库不是Git管理的版本库,那么你必须使用git diff生成的patch才能让你的代码被项目的维护人接受。

 

B.除错功能:对于git diff生成的patch,你可以用git apply --check 查看补丁是否能够干净顺利地应用到当前分支中;如果git format-patch 生成的补丁不能打到当前分支,git am会给出提示,并协助你完成打补丁工作,你也可以使用git am -3进行三方合并,详细的做法可以参考git手册或者《Progit》。从这一点上看,两者除错功能都很强。

 

C.版本库信息:由于git format-patch生成的补丁中含有这个补丁开发者的名字,因此在应用补丁时,这个名字会被记录进版本库,显然,这样做是恰当的。因此,目前使用Git的开源社区往往建议大家使用format-patch生成补丁。

 

git apply

git apply 可以应用使用git diff 和git format-patch生成的2种patch来打补丁.

 

使用git apply 命令之后patch文件中的修改会自动合入到对应的文件中,但是不会帮我们自动提交这个commit.

 

android1@Ubuntu:alps$ git apply 0001-mp3.patch

alps/0001-mp3.patch:30: trailing whitespace.

         //zhangle add start

alps/0001-mp3.patch:32: space before tab in indent.

               mimetype = "application/vnd.android.package-archive";

warning: alps/packages/apps/Browser/src/com/android/browser/DownloadHandler.java has type 100755, expected 100644

warning: 2 lines add whitespace errors.

 

这里只有警告,表示patch已经成功应用了,可以使用git status来查看工作区的文件状态

 

android1@Ubuntu:alps$ git status

# On branch Android_S510_AI-XL_no_codec

# Changes not staged for commit:

#(use "git add <file>..." to update what will be committed)

#(use "git checkout -- <file>..." to discard changes in working directory)

#

#       modified:packages/apps/Browser/src/com/android/browser/DownloadHandler.java

#       modified:packages/providers/DownloadProvider/src/com/android/providers/downloads/OpenHelper.java

#

# Untracked files:

#(use "git add <file>..." to include in what will be committed)

#

#       0001-mp3.patch

no changes added to commit (use "git add" and/or "git commit -a")

 

如果没有什么冲突提示就直接使用git commit提交就可以了

 

如果遇到git apply的空格相关的问题,可以使用—whitespace 参数来尝试解决问题.

android1@Ubuntu:alps$ git apply --whitespace=warn 0001-mp3.patch

 

git am

 

android1@Ubuntu:alps$ git am 0001-mp3.patch

git am 会直接使用patch文件中的diff的信息,还有提交者,时间等等来自动提交,不需要我们再去提交commit

 

git am 必须使用的是用git format-patch 生成的patch文件来打补丁,而不能是使用git diff生成的patch.如果使用的是git diff生成的patch,会出现下面这个错误.

android1@Ubuntu:alps$ git am patch2.patch

Patch format detection failed.

 

使用补丁维护git仓库时遇到的小问题

1、包含二进制文件时的diff和apply

 

foo$ git diff HEAD^..HEAD > foobar.patch

 

bar$ git apply foobar.patch

...

error: cannot apply binary patch to 'root/images/back_disabled.png' without full index line

error: root/images/back_disabled.png: patch does not apply

...

git apply提示错误,无法应用补丁。是因为普通的diff格式文件是不支持二进制文件的,新增的或者发生变化的二进制文件无法在diff文件中体现。git扩展了diff使其支持二进制格式,生成补丁时指定选项--binary即可,生成的文件可以顺利的git apply。

 

$ git diff HEAD^..HEAD --binary > foobar.patch

2、git apply的空白问题

 

$ git apply foobar.patch

foobar.patch:271: trailing whitespace.

foobar.patch:465: space before tab in indent.

.paging_full_numbers a.paginate_active {

warning: squelched 1705 whitespace errors

warning: 1710 lines add whitespace errors.

看看git apply(1)手册上怎么说:

 

– -whitespace=

When applying a patch, detect a new or modified line that has whitespace errors. What are considered whitespace errors is controlled by core.whitespace configuration. By default, trailing whitespaces (including lines that solely consist of whitespaces) and a space character that is immediately followed by a tab character inside the initial indent of the line are considered whitespace errors.

 

By default, the command outputs warning messages but applies the patch. When git-apply is used for statistics and not applying a patch, it defaults to nowarn.

 

You can use different values to control this behavior:

 

nowarn — turns off the trailing whitespace warning.

 

warn — outputs warnings for a few such errors, but applies the patch as-is (default).

 

fix — outputs warnings for a few such errors, and applies the patch after fixing them (strip is a synonym — the tool used to consider only trailing whitespace characters as errors, and the fix involved stripping them, but modern gits do more).

 

error — outputs warnings for a few such errors, and refuses to apply the patch.

 

error-all — is similar to error but shows all errors.

 

git apply应用补丁时会检测空白错误,默认情况下,尾部空白,包含空白的空行,初始tab缩进之后紧跟的空白字符会被认为是错误。

处理这个错误的行为由命令行参数--whitespace或者core.whitespace配置来控制,共有5种可能的动作:

 

nowarn

关闭错误提示

 

warn

输出部分错误提示,但完整的应用补丁,不会处理错误,这是默认动作。

 

fix

输出部分错误,修正错误后应用补丁

 

error

输出部分错误,拒绝应用补丁。

 

error-all

输出全部的错误,拒绝应用补丁。

 

3、patch命令无法处理含有空白的文件名

 

$ patch p1 < foobar.patch

can't find file to patch at input line 716

Perhaps you used the wrong -p or --strip option?

The text leading up to this was:

--------------------------

|diff --git a/root/images/Sorting icons.psd b/root/images/Sorting icons.psd

|new file mode 100644

|index 0000000..53b2e06

|Binary files /dev/null and b/root/images/Sorting icons.psd differ

--------------------------

File to patch:

Skip this patch? [y]

因为diff文件中的文件名含有空格,patch命令无法应用这样的diff补丁。应该避免使用带有特殊字符的文件名。

当然patch也无法引用二进制diff补丁,使用普通diff格式生成含有二进制文件的补丁时,patch会应用成功,但生成的二进制文件是空的。

 

4.错误: previous rebase directory .git/rebase-apply still exists but mbox given.

先执行git am –abort 在执行git am --whitespace=warn 0001-.patch



<think> 我们正在讨论git format-patchgit diff命令,特别是带有--binary--from选项的git format-patchgit diff的区别用法。 根据引用[1]的内容,我们可以总结以下几点: 1. git diff生成的patch兼容性更强,适用于非Git管理的版本库。 2. git format-patch生成的补丁包含开发者信息,并且社区推荐使用。 3. 两者在除错功能上都很强,但方式不同:git diff可以用`git apply --check`检查补丁;git format-patch生成的补丁用`git am`应用,如果失败会提示并可以三方合并(使用`git am -3`)。 用户特别询问了`git format-patch --binary --from``git diff`的使用方法及区别。 首先,我们分别解释这两个命令: 一、`git format-patch`命令 作用:将提交导出为一个或多个补丁文件(每个提交一个文件),通常用于邮件发送。 选项: --binary: 生成二进制的补丁,这样除了文本差异外,还可以包含二进制文件的差异(如图片等)。如果不加这个选项,默认只处理文本文件。 --from[=<name>]: 在补丁的“From”头中添加一个发件人标识。默认使用提交者的名字邮箱,但可以覆盖。 示例: 生成最近一次提交的补丁,并包含二进制文件差异,同时指定发件人标识: ``` git format-patch --binary --from="Your Name <email@example.com>" -1 ``` 二、`git diff`命令 作用:显示工作区、暂存区、提交之间的差异。可以生成一个统一的差异文件(patch),这个patch可以用`git apply`或`patch`命令应用。 它没有`--from`选项,因为git diff生成的补丁不包含作者信息(但会记录差异产生的时间等)。 区别总结: 1. 输出格式: - `git format-patch`生成的是邮件格式的补丁,每个提交单独一个文件,包含提交信息、作者、日期等元数据。 - `git diff`生成的是统一的diff文件,不包含作者信息(除非在提交日志中体现),但包含文件差异。 2. 二进制文件处理: - `git format-patch`默认不处理二进制文件,除非使用`--binary`选项。 - `git diff`在处理二进制文件时,默认会输出二进制文件的差异(但可能不是可应用的形式),或者使用`--binary`选项(在git diff中这个选项已废弃,现在默认行为已经包括二进制差异?)?注意:在git diff中,二进制文件通常以二进制差异的形式表示,但可能无法直接应用。 3. 应用补丁的方式: - `git format-patch`生成的补丁通常用`git am`来应用,这样可以保留提交信息。 - `git diff`生成的补丁用`git apply`或`patch`命令应用,不会创建提交,需要手动提交。 4. 元数据保留: - `git format-patch`会保留作者、提交者、日期等信息,应用补丁时会使用这些信息创建提交。 - `git diff`只包含代码差异,不包含这些元数据。 5. 使用场景: - 当需要将补丁通过邮件列表发送时,使用`git format-patch`,特别是开源项目协作。 - 当需要快速生成一个补丁并应用于另一个分支或仓库(尤其是非Git仓库)时,使用`git diff`。 注意:引用[1]中提到,目前使用Git的开源社区推荐使用`git format-patch`。 因此,对于用户的问题: 使用方法: - `git format-patch --binary --from="Your Name <email@example.com>" <commit>...`:生成从某个提交开始的补丁,包含二进制文件,并设置发件人信息。 - `git diff [<options>] <commit> [<commit>]`:生成两个提交之间的差异,或者工作区与暂存区的差异等。 区别: - `git format-patch`是为每个提交生成一个补丁文件(邮件格式),而`git diff`生成一个统一的差异文件。 - `git format-patch`生成的补丁包含完整的提交信息,而`git diff`不包含。 - `git format-patch`需要配合`git am`使用,而`git diff`生成的补丁用`git apply`或`patch`命令。 另外,关于二进制补丁:在`git format-patch`中,`--binary`选项会生成包含二进制数据的补丁,这样在应用补丁时能够正确地还原二进制文件。而在`git diff`中,虽然它也会尝试表示二进制文件的差异,但可能不如`git format-patch`那样完整(尤其是在跨版本应用时)。 根据以上分析,我们给出回答。 </think>### Git format-patchgit diff 的使用方法及区别分析 #### 🛠️ `git format-patch --binary --from` 使用方法 1. **生成补丁文件**: ```bash # 生成最近一次提交的补丁 git format-patch -1 --binary --from="Author Name <email@example.com>" # 生成特定范围的提交补丁(如HEAD~3到HEAD) git format-patch --binary --from="Author Name" HEAD~3..HEAD ``` - `--binary`:包含二进制文件差异(如图片/压缩包),默认文本补丁不包含二进制变更[^1]。 - `--from`:在补丁头添加作者标识(格式:`From: Author Name <email>`),便于接收方溯源[^1]。 - 输出:每个提交生成独立的 `.patch` 文件(邮件格式)。 2. **应用补丁**: ```bash git am *.patch # 保留提交元数据(作者/时间戳) git am -3 *.patch # 冲突时尝试三方合并 ``` #### 🛠️ `git diff` 使用方法 1. **生成通用补丁**: ```bash # 工作区与暂存区差异 git diff > changes.patch # 两个提交间的差异 git diff commitA..commitB > range.patch # 包含二进制差异(Git 2.32+) git diff --binary HEAD~1 HEAD > bin.patch ``` 2. **应用补丁**: ```bash git apply changes.patch # 仅应用代码变更(不创建提交) git apply --check changes.patch # 检查补丁兼容性 patch -p1 < changes.patch # 非Git环境应用 ``` #### 🔍 核心区别 | **特性** | `git format-patch --binary --from` | `git diff` | |------------------------|-------------------------------------------------------|-------------------------------------| | **输出格式** | 邮件格式(每个提交独立文件) | 统一差异格式(单个文件) | | **元数据保留** | ✅ 提交作者/日期/描述 | ❌ 仅代码差异 | | **二进制支持** | `--binary`显式启用二进制嵌入 | `--binary`选项支持(较新版本) | | **兼容性** | 需Git环境(`git am`) | ✅ 兼容所有版本控制系统(如SVN)[^1] | | **冲突处理** | `git am -3`自动三方合并 | 需手动解决冲突 | | **版本溯源** | 补丁头含作者信息(`--from`自定义)[^1] | 无作者信息 | | **典型场景** | 开源社区协作(如Linux内核邮件列表) | 跨版本系统补丁/快速本地修复 | #### ⚠️ 关键注意事项 1. **二进制处理**: - `git format-patch --binary` 会将二进制文件编码为文本嵌入补丁,确保文件完整性。 - `git diff --binary` 生成类似输出,但需Git 2.32+版本才能完整支持[^1]。 2. **协作规范**: - 开源项目通常要求`git format-patch`,因其保留作者信息便于审核[^1]。 - 私有项目或非Git系统建议用`git diff`保证兼容性。 3. **冲突检测**: ```bash # format-patch生成的补丁检测 git apply --check 0001-feature.patch # diff生成的补丁检测 git apply --check changes.patch ``` > 💡 **经验建议**:需要保留提交历史且接收方为Git仓库时,优先使用`git format-patch`;若需跨系统分发或快速修补,选择`git diff`。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值