git am错误:“补丁不适用”


76

我正在尝试使用git将多个提交从一个项目移至第二个,类似的提交。

所以我创建了一个补丁,其中包含5个提交:

git format-patch 4af51 --stdout > changes.patch

然后将修补程序移动到第二个项目的文件夹,并要应用该修补程序:

git am changes.patch 

...但是它给我错误:

Applying: Fixed products ordering in order summary.
error: patch failed: index.php:17
error: index.php: patch does not apply
Patch failed at 0001 Fixed products ordering in order summary.
The copy of the patch that failed is found in:
   c:/.../project2/.git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

所以我打开了index.php,但是那里什么都没有改变。我假设有一些>>>>>>>标记等,例如在解决合并冲突时,但文件中未标记任何冲突。git status还给了我一个空的已更改文件列表(仅changes.patch存在)。所以我运行git am --continue,但是出现另一个错误:

Applying: Fixed products ordering in order summary.
No changes - did you forget to use 'git add'?
If there is nothing left to stage, chances are that something else
already introduced the same changes; you might want to skip this patch.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort". 

我正在使用Windows 7和最新的git版本“ 1.9.4.msysgit.1”

PS经过数小时的谷歌搜索,我发现了很少的解决方案,但对我没有任何帮助:


git am -3 changes.patch 

给出奇怪的“ sha1信息”错误:

Applying: Fixed products ordering in order summary.
fatal: sha1 information is lacking or useless (index.php).
Repository lacks necessary blobs to fall back on 3-way merge.
Cannot fall back to three-way merge.
Patch failed at 0001 Fixed products ordering in order summary.
The copy of the patch that failed is found in:
   c:/.../project2/.git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort". 

git am changes.patch --ignore-whitespace --no-scissors --ignore-space-change

给出上面的第一个错误:“错误:修补程序失败:index.php:17”,但未index.php添加任何冲突标记。


5
我也一直在为此苦苦挣扎。但是在某些情况下,这是由CRLF在行尾时提交的文件(例如,来自Windows来源)引起的。尽管有eol.crlf之类的配置功能,但git似乎不喜欢CRLF行尾。有关cr / lf问题的示例链接:stackoverflow.com/questions/1510798/…–
Rob

1
大。只需将我收到的补丁程序的行尾转换为“ Unix”样式,然后便可以使用。那赢得了赞成。
user2808624 '16

Answers:


106

什么是补丁?

补丁程序(参见下文)仅比一系列说明要多:“在此添加”,“在此删除”,“将第三件更改为第四件”。这就是为什么git告诉您:

The copy of the patch that failed is found in:
c:/.../project2/.git/rebase-apply/patch

您可以在您喜欢的查看器或编辑器中打开该补丁,在您喜欢的编辑器中打开要更改的文件,然后使用您所知道的(而不是git不知道)“手动应用”该补丁,以了解如何“添加”如果要更改的文件现在看起来或像以前更改时所做的那样几乎没有或根本没有变化,而这些更改将作为补丁提供给您,则请执行此操作。

再来一点

三向合并引入的信息要比普通的“一系列指令”多得多:它告诉您文件的原始版本也是如此。如果您的存储库具有原始版本,则您的git可以将对文件所做的操作与补丁对文件所做的操作进行比较。

如您在上面看到的,如果您请求三向合并,则git在另一个存储库中找不到“原始版本”,因此它甚至无法尝试三向合并。结果,您将没有冲突标记,并且必须手动执行补丁程序。

使用 --reject

当您必须手动应用修补程序时,git仍然有可能自动为您应用大部分修补程序,而只剩下几块能够推理代码(或需要修补的内容)的实体。添加命令--rejectgit这样做,并将补丁的“不适用”部分保留在拒绝文件中。 如果使用此选项,则仍必须手动应用每个失败的补丁程序,并弄清楚如何处理被拒绝的部分。

完成必要的更改后,就可以git add修改文件了,并git am --continue用来告诉git提交更改并继续下一个补丁。

如果无事可做怎么办?

由于我们没有您的代码,所以我无法确定是否是这种情况,但是有时候,您会发现其中一个补丁说明了诸如“修复第42行的单词的拼写”之类的内容。当那里的拼写已经固定。

在这种特殊情况下,您在查看了补丁程序和当前代码后应该对自己说:“啊哈,应该完全跳过补丁程序!” 那是当您使用已经打印的其他建议git时:

If you prefer to skip this patch, run "git am --skip" instead.

如果运行git am --skip,git将跳过该修补程序,因此,如果邮箱中有五个修补程序,它将最终仅添加四个提交,而不是五个提交(如果跳过两次,则三个而不是五个),依此类推)。


11
谢谢您的好评。该git am changes.patch --reject是最适合我的,因为它提供了替代的“冲突标志”(在名为.rej文件中找到)。然后git addgit am --continue一切正常:-)
nanuqcz 2014年

2
是的,谢谢。令我感到惊讶的是,它git am没有(例如patch)尝试应用确实适用的更改。
史蒂文·R·鲁米斯

git有时无法应用自身产生的补丁,这似乎很奇怪。我正在使用git log --pretty=email --patch-with-stat --reverse -- filename
Ed Randall

3
@EdRandall:如果您使用git amgit apply -3 并且您在存储库中拥有文件的基本版本,则Git应该能够进行三向合并(当然,可能存在合并冲突)。请注意,您可能需要发送补丁的人员--full-index在生成补丁时使用。
torek '17

1
@DrumM:merge和rebase始终具有基本文件,因此它们实际上不需要等价的,--reject因为它们始终具有的等价物-3。就是说,我已经习惯了GNU风格的patch命令,所以我通常也更喜欢这种--reject模式,但是我可以以任何一种方式看到参数。
torek

4

git format-patch也有-B国旗。

手册页中的描述还有很多需要改进的地方,但是用简单的语言来说,它是在完全重写文件之前要遵循的阈值格式补丁(通过一次删除所有旧文件,然后插入一次一切都是新的)。

当手动编辑太麻烦并且来源比我的目的地更具权威性时,这对我来说非常有用。

一个例子:

git format-patch -B10% --stdout my_tag_name > big_patch.patch
git am -3 -i < big_patch.patch


2

我有同样的问题。我曾经用过

git format-patch <commit_hash>

创建补丁。我的主要问题是补丁由于某些冲突而失败,但是我看不到文件内容中的任何合并冲突。我曾经git am --3way <patch_file_path>申请过补丁。

应用补丁的正确命令应该是:

git am --3way --ignore-space-change <patch_file_path>

如果执行上述命令进行修补,则如果应用修补失败,则会产生合并冲突。然后,您可以解决文件中的冲突,就像解决git merge合并冲突的方法一样


1
参数-3Way错误,为-3--3way。这不能回答问题。
DrumM

1
这是代码部分的错字。感谢您指出。如果您遵循了完整的答案,则可能已经注意到,在文本部分中,以粗体显示了--3Way。根据该问题,在应用补丁后,合并冲突没有显示出来。我有同样的问题,仅使用该命令即可解决。
srs

1)您放置--在之后...should be:,这已经看起来像是错字,我很容易阅读了--下面的代码行。2)只是烦恼代码答案不包含正确答案;-)最好只显示正确的代码。3)原始问题中的错字不是引起他的问题的原因
DrumM

2
我不知道为什么会这样,但是--ignore-space-change选项是使补丁文件正常工作的原因。
天空

1

此类错误可能是由于LF与CRLF行末尾不匹配而引起的,例如,当您查看补丁文件时,您绝对确定它应该可以应用,但不会。

为了测试这一点,如果您有仅适用于一个文件的补丁,则可以尝试在该文件上运行“ unix2dos”或“ dos2unix”(尝试两者,以查看哪个引起文件更改;您可以获取这些文件Windows和Unix实用工具),然后将该更改作为测试提交提交,然后尝试再次应用补丁。如果那行得通,那就是问题所在。

NBgit am默认情况下将补丁应用为LF(即使补丁文件包含CRLF),因此,按照此答案,如果要将CRLF补丁应用到CRLF文件,则必须使用。git am --keep-cr


0

如果有几个模块抱怨补丁不适用。我错过的一件事是树枝变得陈旧。之后,git merge master利用产生的补丁文件git diff master BRANCH > file.patch。去香草支行可以用git apply file.patch


0

我遇到了同样的错误。创建补丁时,我还原了提交版本。它的工作方式与早期补丁相反。

[mrdubey @ SNF] $ git log 65f1d63 commit 65f1d6396315853f2b7070e0e6d99b116ba2b018作者:Dubey Mritunjaykumar

日期:2019年1月22日星期二12:10:50 +0530

提交e377ab50081e3a8515a75a3f757d7c5c98a975c6作者:Dubey Mritunjaykumar日期:2019年1月21日星期一23:05:48 +0530

先前的常用命令:git diff new_commit_id..prev_commit_id> 1 diff

得到错误:修补程序失败:文件名:40

工作之一:git diff prev_commit_id..latest_commit_id> 1.diff

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.