如何将 Git 补丁应用到具有不同名称和路径的文件?

我有两个仓库。在其中一个示例中,我对文件 ./hello.test进行了更改。我用 git format-patch -1 HEAD提交更改并从中创建一个补丁。现在,我有了第二个存储库,其中包含一个文件,其内容与 hello.test 相同,但是放在另一个目录中,名称不同: ./blue/red/hi.test。如何将上述补丁应用到 hi.test文件?我试过 git am --directory='blue/red' < patch_file,但它当然会抱怨文件的名称不一样(我以为 Git 不在乎这一点).我知道我可以编辑差异应用于该特定的文件,但我正在寻找一个命令解决方案。

68134 次浏览

您可以使用 git diff创建补丁,然后使用 patch实用程序应用它,它允许您指定要应用 diff 的文件。

例如:

cd first-repo
git diff HEAD^ -- hello.test > ~/patch_file


cd ../second-repo
patch -p1 blue/red/hi.test ~/patch_file

有一个简单的解决方案,不涉及手动补丁编辑或外部脚本。

在第一个存储库中(这也可能导出一个提交范围,如果只想选择一个提交,则添加 -1标志) :

git format-patch --relative <committish> --stdout > ~/patch

在第二个存储库中:

git am --directory blue/red/ ~/patch

与在 git format-patch中使用 --relative不同,另一种解决方案是在 git am中使用 -p<n>选项从补丁的路径中剥离 n目录,如在 回答类似的问题中所提到的。

也可以在没有 --stdout的情况下运行 git format-patch --relative <committish>,它将生成一组 .patch文件。这些文件可以直接提供给 git amgit am --directory blue/red/ path/to/*.patch

我知道这两个文件在你的情况下是完全一样的,因此补丁很可能会成功。

但是 如果您想对类似但不完全相同的文件应用补丁,或者您想进行交互式补丁,您将使用三种方式合并。

假设您修改了文件 A,让我们将 A~1表示为以前的版本,并且您希望应用 A~1A到文件 B之间的差异。

打开一个三路合并工具,例如 Beyond Compare,左边面板的路径是 A,中间面板是共同的祖先,所以路径是 A~1,右边面板的路径是 B。然后,下面的面板显示了对文件 B应用 A~1A之间的区别的结果。

下图说明了这个想法。

enter image description here

基于@georgebrock 给出的答案,下面是我使用的一个解决方案:

首先,像往常一样创建补丁文件(例如 git format-patch commitA..commitB)。

然后确保您的目标存储库是干净的(不应该有任何更改或未跟踪的文件) ,并像下面这样应用补丁:

cd second-repo
git am ~/00*.patch

对于每个补丁文件,您都会得到一个错误,比如“ error: XYZ does not live in index”。您现在可以手动应用这个补丁文件:

patch --directory blue/red < ~/0001-*.patch
git add -a
git am --continue

对于每个补丁文件,您必须执行以下三个步骤。

这将保留原始提交消息等,而不需要任何特殊的 git format-patch命令或编辑补丁文件。

仅供参考: 我最近在试图从 Github 下载一个补丁并将其应用到本地文件(这是一个新位置的“覆盖”)时遇到了问题。

git am也不会应用补丁程序,因为文件“不在索引中”或“脏”但是,我发现简单的 patch命令 可以应用了补丁。它确实提示我要修补文件的名称。

不管怎样,我完成了任务。