git-apply 神秘地失败了,我该如何排除/修复?

Posted

技术标签:

【中文标题】git-apply 神秘地失败了,我该如何排除/修复?【英文标题】:git-apply fails mysteriously, how do I troubleshoot/fix? 【发布时间】:2013-01-16 23:03:13 【问题描述】:

我目前正在尝试对 (github) 存储库的 PR 进行代码样式检查,并且我想向提交者提供补丁,以便他们可以轻松地修复代码样式。为此,我正在拉下他们的 PR,在其上运行我们的 uncrustify 脚本以修复任何样式错误,并希望创建一个他们可以轻松应用的 .patch 文件。但是,它始终会在某些文件上中断。

我愿意(带有core.autocrlf=inputcore.filemode=false 的 git 版本 1.7.10.4):

$ git checkout pr-branch
$ git log -1 (shows: commit dbb8d3f)
$ git status (nothing to commit, working directory clean)
$ <run the code styler script, which modifies some files>
$ git diff > ../style.patch (so the patch file lands outside the repo)
$ git reset --hard HEAD (to simulate the situation at the submitter's end)
$ git log -1 (shows: commit dbb8d3f)
$ git status (nothing to commit, working directory clean, so we are where we started)
$ git apply ../style.patch
error: patch failed: somefile.cpp:195
error: somefile.cpp: patch does not apply (same output using the --check option)

这仅适用于某些文件,而不是所有文件。我不知道如何解决这个问题,即如何让 git 准确地告诉我哪里出了问题——当我挖掘时它只会告诉我一个大块头#,但这仍然是相当大的。

到目前为止我尝试过的(没有成功):

    apply --reverse, apply --whitespace=nowarn diff HEAD 而不是单独的diff 进行虚拟提交(提交工作没有问题!),使用format-patch,删除虚拟提交,使用git-am 应用补丁,带或不带-3,或使用git-apply 将补丁文件放在本地目录中,而不是一个向上(抓住稻草,在这里) 查看 git-diff、-apply、-format-patch、-am 的手册页是否有用 用 linux patch 命令打补丁 ....

我不知道差异可能有什么问题。空白的东西应该只警告,对吧?在任何情况下,我都不想忽略它们,因为它是一种明显涉及空白的样式修复。

我该如何解决/诊断这个问题,甚至找出它的确切位置?如果我发布其中一个罪魁祸首文件的差异会有帮助吗?让我感到困惑的是,提交工作没有问题,但从提交创建的补丁却没有??

在与这个问题搏斗了几个小时后,我的知识已经走到了尽头......

【问题讨论】:

git apply --reject 查看被拒绝的更改。 已经试过了...这只显示了失败的整个大块(在这种情况下大约 2-300 行),所以信息量不是很大 另一个猜测 - 可能有一些文件重命名,结果可能会变成“gitignored”。 不,这只是文本文件中的样式更改,没有重命名。 Franci 的 --index 选项似乎解决了这个问题。 遇到了同样的问题。对我有帮助的是--whitespace=fix,但我仍然不明白为什么,因为我刚刚创建了补丁并没有手动编辑它。 【参考方案1】:

在这种情况下,如果您已经尝试了下面列出的所有选项:

    调查文件中潜在的不可打印/不可见字符 使用dos2unix进行转换 更改 git 配置以调整处理行尾的方式,例如:
git config --global core.autocrlf input

在这种情况下,另一个邪恶的根源可能是您的 IDE。

例如,一些 JetBrains IDE 像 phpStorm 有以下选项:

今天在一个奇怪的补丁问题上花费了 4 个多小时的血腥时间后,最终出现以下错误:

git apply < my.git.patch --verbose
...
error: patch failed: plugins/some/file.php:74

我意识到我是我的编辑器的受害者(我不确定这是否是默认行为)。

我使用 PHPStorm 检查补丁文件,它默默地从补丁文件中删除了一个空格,该空格确实存在于需要修补的目标文件中。

这太狡猾了,我最终将 Strip trailing spaces on Save for 选项设置为 None 以不再遇到此类问题。

另外请记住,与平台相关的差异,例如底层文件系统(例如 MacOS/Linux)的区分大小写也可能是问题所在。

【讨论】:

【参考方案2】:

尝试检查您的补丁文件 - 示例:

git apply --reject mypatch.patch

这将向您展示差异(如果有的话) - 这是它的外观示例:

error: patch failed: <filename>:<linenumber>
error: while searching for :
    cout << "" << endl; // example of a line in your patch

【讨论】:

@YasinOkumuş 你是对的,它不能解决问题,但它会跳过错误并应用其余部分并解释原因,所以基本上你可以要求的就是:)【参考方案3】:

更新:

您可以使用git apply -v 查看有关正在发生的事情的更多详细信息,git apply --check 仅用于验证操作,或git apply --index 用于重建本地索引文件。

根据您的评论,您的本地索引似乎已损坏,因此 index 解决了它。

我将留下我最初的答案和 cmets,主要是为了让人们了解正在发生的事情,因为我怀疑其他人会根据问题描述得出与我相同的初步结论。

-----

差异很可能没有任何问题。而是查看目标 git 存储库。当您使用git reset --hard HEAD 时,没有任何东西可以保证您在另一个存储库上的HEAD 与您的HEAD 相同。

在目标 repo 上执行 git log 并查看顶部的提交。它与您制作差异的那个相同吗?很可能不是。查看历史记录并检查您需要的提交是否存在。如果是,那么目标 repo 就在你之前,你必须回去,做git pull(或git rebase)并产生一个新的差异。如果不是,那么目标 repo 就在你的后面,你需要在目标 repo 上执行git pull(或git rebase)以加快速度。

请记住,如果您有其他人致力于您的“主”存储库(您的机器人和目标存储库从中提取的那个),您可能必须 git pull 两个存储库,以使它们合理最近的共同提交。

【讨论】:

在我上面描述的过程中,当前的 HEAD 对于差异创建和差异应用程序都是相同的。这是该分支中的最后一次提交。我完全重置以消除来自不同 HEAD 的任何问题。所以不可能。必要时更新已经自动处理了,但是如果在上述测试情况下apply不起作用,它也会在那里失败,所以必须提前解决。 如果HEADs 都指向同一个提交,您的描述并不清楚。我的猜测是它们不是,但如果你检查它们并且它们是,那么差异确实有问题。 另外,尝试git apply -v,或使用--check-index 选项。 真的吗?如果我所做的只是 git-checkout、更改一些文件然后 git-reset --hard HEAD,而不在两者之间提交,那么 HEAD 怎么会有所不同?我已经尝试过这些选项,但我得到的只是一些关于空格的东西。会再做一次并发布更多信息。 git checkoutgit reset 都是本地存储库命令。除非目标 repo 是源 repo 的上游 repo(在这种情况下,我希望你做 git push,而不是做差异),你必须在结帐前做 git pullgit rebase

以上是关于git-apply 神秘地失败了,我该如何排除/修复?的主要内容,如果未能解决你的问题,请参考以下文章

Python程序运行了一周,然后神秘地失败了

CORS 预检神秘地因大猩猩/处理程序而失败

我该如何调查这些神秘的 Django 崩溃?

GROUP BY 子句在 IBM dashDB 中神秘地失败

iOS 上 jQuery.each() 和 Underscore.each() 的神秘失败

.htaccess 重写失败,不确定如何排除故障