【问题标题】:git am error: "patch does not apply"git am 错误:“补丁不适用”
【发布时间】:2014-11-08 20:52:52
【问题描述】:

我正在尝试使用 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”

附:经过几个小时的谷歌搜索,我找到了一些解决方案,但对我来说没有任何效果:


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 中没有添加冲突标记。

【问题讨论】:

  • 我也一直在为此苦苦挣扎。但在某些情况下,它是由在 CRLF 处于行尾时提交的文件(来自例如 WINdows 源)引起的。尽管有像 eol.crlf 这样的配置功能,git 似乎不喜欢 CRLF 行结尾。关于 cr/lf 问题的示例链接:stackoverflow.com/questions/1510798/…
  • 太棒了。只需将我收到的补丁的行尾转换为“Unix”风格,然后它就可以工作了。这赢得了支持。

标签: git


【解决方案1】:

我遇到了同样的问题。我用过

git format-patch <commit_hash>

创建补丁。我的主要问题是补丁由于某些冲突而失败,但我在文件内容中看不到任何合并冲突。我使用了git am --3way &lt;patch_file_path&gt; 来应用补丁。

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

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

如果你执行上面的命令打补丁,如果补丁应用失败会产生合并冲突。然后您可以修复文件中的冲突,就像解决 git merge

的合并冲突一样

【讨论】:

  • 参数-3Way有误,要么是-3要么是--3way。这并不能回答问题。
  • 这是代码部分的错字。感谢您指出。如果您遵循了完整的答案,您可能已经注意到,在文本部分中提到了 --3Way 粗体。根据问题,应用补丁后没有显示合并冲突。我有同样的问题,我只使用该命令解决了它。
  • 1) 你把-- 放在...should be: 之后,这看起来已经是一个错字了,我很容易阅读-- 并阅读下面的代码行。 2)只是讨厌代码答案不包含正确的答案;-)最好只提供正确的代码。 3)原始问题中的错字并没有导致他的问题......
  • 我不知道具体原因,但 --ignore-space-change 选项是我的补丁文件起作用的原因。
  • 这对我有用。在我的情况下,我仍然有合并冲突,但是这个命令像往常一样设置冲突文件。我能够使用git mergetool 解决冲突。
【解决方案2】:

这种错误可能是由 LF 与 CRLF 行尾不匹配引起的,例如当您查看补丁文件并且您绝对确定它应该能够应用时,但它不会。

要对此进行测试,如果您有一个仅适用于一个文件的补丁,您可以尝试仅在该文件上运行“unix2dos”或“dos2unix”(同时尝试两者,看看哪个会导致文件更改;您可以为 Windows 和 Unix 获取这些实用程序),然后将该更改作为测试提交提交,然后再次尝试应用补丁。如果可行,那就是问题所在。

NB git am 默认情况下将补丁应用为 LF(即使补丁文件包含 CRLF),因此如果您想将 CRLF 补丁应用于 CRLF 文件,您必须使用git am --keep-cr,按照this answer.

【讨论】:

    【解决方案3】:

    我遇到了同样的错误。我在创建补丁时恢复了提交版本。它的工作原理与之前的补丁相反。

    [mrdubey@SNF]$ git log 65f1d63 提交 65f1d6396315853f2b7070e0e6d99b116ba2b018 作者:杜比 Mritunjaykumar

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

    提交 e377ab50081e3a8515a75a3f757d7c5c98a975c6 作者:杜贝·姆里通贾伊库马尔 日期: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

    【讨论】:

      【解决方案4】:

      有几个模块抱怨补丁不适用。我错过的一件事是树枝已经过时了。在git merge master 使用git diff master BRANCH &gt; file.patch 生成补丁文件之后。去原版分支可以用git apply file.patch打补丁

      【讨论】:

        【解决方案5】:

        我遇到了这个错误,可以通过使用来克服它: patch -p1 &lt; example.patch

        我从这里拿走了它: https://www.drupal.org/node/1129120

        【讨论】:

          【解决方案6】:

          git format-patch 也有 -B 标志。

          手册页中的描述还有很多不足之处,但用简单的语言来说,它是在完全重写文件之前将遵守的阈值格式补丁(通过一次删除所有旧文件,然后是单次插入所有新内容)。

          当手动编辑过于繁琐且来源比我的目的地更权威时,这对我来说非常有用。

          一个例子:

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

          【讨论】:

            【解决方案7】:

            什么是补丁?

            补丁只不过是一系列指令(见下文):“在此处添加”、“在此处删除”、“将第三项更改为第四项”。这就是 为什么 git 告诉你:

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

            您可以在您喜欢的查看器或编辑器中打开该补丁,在您喜欢的编辑器中打开要更改的文件,然后使用您所知道的“手动应用”补丁(以及git 没有)弄清楚当要更改的文件现在看起来很少或根本不像之前更改时所做的那样时,要弄清楚 如何 “在此处添加”更改以补丁的形式交付给您。

            多一点

            三路合并比简单的“一系列指令”引入了“略多”的信息:它还告诉您文件的原始版本是什么。如果您的存储库具有原始版本,您的 git 可以比较 对文件所做的操作,以及 patch 对文件所说的操作。

            如你所见,如果你请求三路合并,git在另一个仓库中找不到“原始版本”,所以它甚至无法尝试三路合并。因此,您不会得到任何冲突标记,并且您必须手动执行补丁应用程序。

            使用--reject

            当您必须手动应用补丁时,git 仍然有可能会自动为您应用 大部分 的补丁,并且只留下少数部分给能够推理的实体代码(或任何需要修补的代码)。添加--reject 告诉git 这样做,并将补丁的“不适用”部分留在拒绝文件中。 如果您使用此选项,您仍必须手动应用每个失败的补丁,并弄清楚如何处理被拒绝的部分。

            完成所需的更改后,您可以git add 修改的文件并使用git am --continue 告诉 git 提交更改并继续下一个补丁。

            如果无事可做怎么办?

            由于我们没有您的代码,因此我无法确定是否是这种情况,但有时,您最终会看到其中一个补丁说的内容相当于,例如,“修复一个单词的拼写第 42 行“当那里的拼写已经固定时。

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

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

            如果你运行git am --skip,git 会跳过那个补丁,所以如果邮箱中有五个补丁,它最终只会添加四个提交,而不是五个(或者如果你跳过两次,三个而不是五个,等等)。

            【讨论】:

            • 感谢您的出色回答。 git am changes.patch --reject 最适合我,因为它提供了“冲突标记”(在 .rej 文件中找到)的替代方案。然后git addgit am --continue 一切正常:-)
            • 好的,谢谢。令我惊讶的是,git am 没有(如patch)尝试应用确实应用的更改。
            • git 有时无法应用自己生成的补丁似乎很奇怪。我正在使用git log --pretty=email --patch-with-stat --reverse -- filename
            • @EdRandall:如果您使用git amgit apply -3 并且您的存储库中有该文件的基本版本,Git 应该能够执行三个-方式合并(当然有潜在的合并冲突)。请注意,您可能需要发送补丁的人在生成补丁时使用--full-index
            • @DrumM:merge 和 rebase 总是有基本文件,所以它们实际上并不需要相当于--reject,因为它们总是有相当于-3 .也就是说,我已经习惯了 GNU 风格的 patch 命令,所以我通常也更喜欢 --reject 模式,但无论哪种方式我都可以看到参数。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-05-21
            • 2011-06-13
            • 2016-12-21
            • 2018-06-29
            • 2018-08-25
            • 1970-01-01
            • 2020-10-22
            相关资源
            最近更新 更多