git apply 失败,显示“补丁不适用”错误。

523
我有一个叫做my_pcc_branch.patch的补丁。
当我尝试应用它时,我收到以下信息:
$ git apply --check my_pcc_branch.patch
warning: src/main/java/.../AbstractedPanel.java has type 100644, expected 100755
error: patch failed: src/main/java/.../AbstractedPanel.java:13
error: src/main/java/.../AbstractedPanel.java: patch does not apply

这是什么意思?
我该如何解决这个问题?

有没有AbstractedPanel.java.rej文件遗留?通常这意味着源代码和补丁中都发生了行机器人的更改(这里似乎影响了第13行)。 - Rudi
不,我没有找到任何*.rej文件。 - Glory to Russia
你尝试过向git@vger.kernel.org报告错误吗?Git的所有描述选项都无法正常工作,返回大量错误。我不得不退回到WinMerge。 - Puterdo Borato
对我来说,这意味着我正在应用已经存在的补丁,顺便说一句...遗憾的是它没有给出更有意义的消息... - rogerdpack
14个回答

675

git apply --reject --whitespace=fix mychanges.patch 对我有效。

解释

--reject 选项告诉 git 不要在无法确定如何应用补丁时失败,而是应用它可以应用的单个块,并为它无法应用的块创建拒绝文件(.rej)。Wiggle 可以“应用[这些]被拒绝的补丁并执行逐字比较”。

此外,--whitespace=fix 将警告有关空格错误并尝试修复它们,而不是拒绝应用其他情况下适用的块。

这两个选项一起使应用补丁更加健壮,可以避免失败,但是需要对结果进行额外注意。

有关整个文档,请参见https://git-scm.com/docs/git-apply


11
这对我来说更有效,因为它并没有完全修改我的文件。 - Wayne Werner
14
很棒。只需拒绝它无法自行解决的内容,然后您可以手动修改被拒绝的文件。 - Dennis
10
当无法自动检测如何应用补丁时,此命令会创建.rej文件。您可以使用Wiggle解决此类问题。 - goodniceweb
19
这个回答没有解释任何东西,特别是在哪些情况下它会起作用。人们,你们真的必须更加要求回答质量,这并不是一个论坛。 - Oliver
2
这样做后,接着运行 wiggle --replace file file.rej 并解决文件中剩余的冲突(美丽的 IDE 支持会提供帮助),问题就得到了解决。非常感谢,你让我的一天变得美好 :pray: - silopolis
显示剩余5条评论

403

msysgit@googlegroups.com邮件列表的Johannes Sixt建议使用以下命令行参数:

git apply --ignore-space-change --ignore-whitespace mychanges.patch

这解决了我的问题。


31
有人可以帮助我并解释一下为什么这样能行吗?另一个答案对我没有用,而我遇到了与提问者描述的问题完全相同的情况。文件属性与忽略空格有什么关系? - skrebbel
3
尝试使用“-C1”开关进行应用,它会减少被视为重要的添加周围的上下文。 - Amir Ali Akbari
1
@skrebbel:毫无疑问,这是由于本地文件系统和远程仓库之间的行结尾不同造成的。在某些配置下,Git会使用Windows-UNIX行结尾转换进行魔法操作(我建议不要这样做)。编辑器应该被配置为不进行转换。文件属性可能不相关。有一个“.gitattributes”文件,但这似乎对常见情况来说过于复杂了。 - Eric Walker
3
@EricWalker,CR/LF与git的魔法不一定是坏事。另一种选择可能是,你修改的每个文件中的每一行都被改变了换行符,导致你提交的变更集有一半都是这种无关紧要的变化,而真正的修改藏在其中某个地方。 - jwg
3
有时这有帮助。但其他时候,尽管补丁本应该能够无问题地应用,我仍然会收到“补丁不适用”的消息。 - Thomas Levesque
显示剩余6条评论

264

当一切尝试失败时,请尝试使用 git apply--3way 选项

git apply --3way patchFile.patch

--3way
当补丁无法干净地应用时,如果补丁记录了它所应用到的 blob 的标识,并且我们在本地拥有这些 blob,则可以回退到三向合并,并可能在工作树中为用户留下冲突标记以供解决。该选项意味着 --index 选项,并且与 --reject 和 --cached 选项不兼容。

典型的失败情况将尽可能应用补丁,并在 Git 中留下冲突供您解决。这比使用 reject 选项更容易一步。


4
这是对我有用的答案。我正在打补丁的文件没有反映出我所生成的补丁的更改(因为我在创建补丁后删除了这些更改)。 - Christia
3
好的通用解决方案。 3向差异看起来与通常不同,有点困惑,但尽管如此,这使我能够解决冲突并使修补程序得以应用。 - steinybot
27
我认为应该将--3way作为默认行为。当补丁失败时,至少告诉我哪里出了问题,这样我就可以手动修复。git apply只是失败了,并没有报告失败的原因。我甚至找不到像hg生成的*.rej文件。 - Pavan Manjunath
14
最佳方案就是让用户解决自己的冲突!请注意,我已经尽力保持原意并使句子通俗易懂。 - Mosh Feu
3
"--3way"比"--reject"更好,因为你最终会得到普通的合并冲突,而每个Git开发人员都习惯于解决这种冲突。 - Mecki
显示剩余7条评论

65

这个命令将应用补丁但不解决它,留下坏文件作为*.rej

git apply --reject --whitespace=fix mypath.patch

你只需要解决它们。解决后运行:

git -am resolved

9
如何解决 *.rej 文件——我所能找到的方法就是在源文件中手动进行更改并删除这些 .rej 文件。还有其他方法吗? - coding_idiot
1
像往常一样,只需检查.rej文件,将其与冲突文件进行比较,最后将修复的文件添加到索引中(使用“git add FIXED_FILES”)。 - Ivan Voroshilin
5
@coding_idiot,你可以使用wiggle来解决问题。例如:wiggle --replace path/to/file path/to/file.rej。这个命令将会把.rej文件中的更改应用到原始文件中,并创建一个原始文件的副本,如 path/to/file.porig。请查看文档以获取有关wiggle的更多信息。 - goodniceweb

42

5
我知道这样做不太好,但是非常感谢你!节省了我数小时的时间。我一直在遇到“补丁无法应用”和各种错误。 - sudo rm -rf slash
1
@sudorm-rfslash,为什么我们不应该这样做,而你为什么还在这样做? - Black
3
命令是 patch,而不是 git patch。请参阅 patch(1) - HeySora
2
这就是正确的方式。忘掉 git patch - Charlton Provatas
如果你使用的是Windows系统,你可能没有patch命令,但你可以使用TortoiseMerge或其他工具打开并应用.patch文件。重要的是,不要使用git! - c z
显示剩余2条评论

18
当你混合使用UNIX和Windows git客户端时,会发生这种情况,因为Windows实际上没有"x"位的概念,所以在Windows下检出一个rw-r--r--(0644)文件时,msys POSIX层会将其“提升”为rwx-r-xr-x(0755)。Git认为该模式差异基本相当于文件中的文本差异,因此您的补丁不能直接应用。我认为您唯一的选择是使用git-configcore.filemode设置为false
这里有一个msysgit问题,其中包含一些相关信息:http://code.google.com/p/msysgit/issues/detail?id=164(重定向到archive.org的2013年12月3日副本)。

2
我尝试运行命令 "git config core.filemode false",但它没有帮助 - 我仍然收到相同的消息。 - Glory to Russia
1
假设您的代码库中没有未提交的更改,请尝试使用 git reset --hard HEAD 命令,以强制 Git 使用新选项重新检出文件。 - Ben Jackson
刚刚尝试执行了 "git reset --hard HEAD" 命令。它成功了(我看到了消息 "HEAD is now at ..."),但是 "git apply" 的问题仍然存在。 - Glory to Russia

13
只需使用 git apply -v example.patch 命令查看“补丁无法应用”的原因,然后逐一修复它们。

8
在我的情况下,我太愚蠢了,第一次创建补丁文件时错误地进行了差异对比。最终导致我得到了完全相同的错误信息。
如果你在主分支上执行git diff branch-name > branch-name.patch,它会尝试删除所有你希望发生的添加操作,反之亦然(这是Git无法实现的,因为显然从未进行过的添加操作无法被删除)。
所以,请确保你切换到你的分支并执行git diff master > branch-name.patch

我犯了同样的错误,请看chimurai的答案 https://dev59.com/3G445IYBdhLWcg3wnrrM#65357332 - fbiagi

6

git apply --reverse --reject example.patch

当你使用相反的分支名称创建补丁文件时:

例如,使用git diff feature_branch..master而不是git diff master..feature_branch


1

警告:该命令可以永久删除旧的丢失提交。在尝试此操作之前,请先备份整个存储库。

我找到了这个链接

我不知道为什么这行得通,但我尝试了许多解决方法,这是唯一一个对我有效的方法。简而言之,请运行以下三个命令:

git fsck --full
git reflog expire --expire=now --all
git gc --prune=now

4
这是一个非常危险的命令,可以从reflog中永久删除旧的丢失提交记录。如果您的代码库状态不稳定,请勿执行此操作。 - E. T.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接