git apply不尊重使用' git mv '的文件重命名



我已经创建了一个不同于其他分支' main '的更改,如下所示:

// while on another branch that is not `main`
git diff main > my-diff.patch

然而,当我运行git apply my-diff.patch时,我看到我的文件重命名(使用git mv)不被尊重。相反,我看到重命名的文件被删除,使用git mv创建的文件作为一个全新的文件。

我如何让git apply尊重我使用git mv之前使用的文件重命名?

Git在跟踪文件重命名方面有点特殊——简而言之,它没有。

这是有意义的,因为git实际上根本不跟踪更改—每次提交都是整个存储库的快照。所以尽管有一个"git "命令,实际上没有任何地方记录你使用了它——所有的git记录都是结果,这就像你删除了原始文件,然后从内存中重新输入了新的文件一样。

让人有点困惑的是git偶尔假装知道移动或复制文件是什么意思。它通过在查看diff时猜测创建和删除实际上是一起进行的来实现这一点。它可以在任何时候进行猜测,并且一些命令有选项可以使它在显示内容时不猜测或更努力地猜测。

So "git apply"做了正确的事情:它创建了一个相当于移动文件的存储库状态。提交该状态,文件将在所有相同的位置显示为重命名或未命名,就像您运行"git mv"一样。

这可以在Git 2.35 (Q1 2022)中更好地工作。

"git apply --3way">(man)在更多的情况下绕过尝试使用三路应用程序来解决由于最近使用直接应用程序作为回退而导致的回归。

见commit 34d6070 (17 Dec 2021) by Jerry Zhang (jerry-skydio)。
(由juno C Hamano—gitster—在commit bc61dba, 10 Jan 2022中合并)

git-apply:在添加/重命名情况下跳过三通道

署名:Jerry Zhang

对"git apply --3way">(man)将尝试三种方式并由于缺少对象而失败,即使git(man)能够返回到apply_fragments并成功应用补丁并返回值为0。要解决这个问题,可以在以下情况下提前从try_threeway()返回:

  • 当补丁为重命名且没有更改行时。在这种情况下,"git diff">(man)不记录blob信息,所以3way既不可能也没有必要。
  • 当补丁是添加的并且没有add/add冲突时,即direct_to_threeway为false。
    在这种情况下,threeway将失败,因为预映像不在缓存中,但由于没有冲突,因此没有必要。

这修复了在--3way应用这些类型的补丁时一些不必要的错误消息。

它还修复了一个报告的问题,即应用几个git(man)生成的补丁的连接将在这些补丁涉及删除之后创建相同的文件时失败。