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


100

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


Answers:


97

您可以使用来创建补丁git diff,然后使用该patch实用工具来应用它,该实用工具允许您指定要将差异应用到的文件。

例如:

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

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

7
啊,很好,没想到。但是,有什么方法可以使用Git命令执行此操作,以使提交数据(日期和时间,提交作者,提交消息)保持不变?
mart1n

2
您可能会使用am或进行某些操作apply,但我找不到它。如果您发现重复更改很多,则可能有使用子模块的更好解决方案,或者您选择的语言提供的共享代码的任何解决方案(例如,在Ruby中,您可以将重复代码提取为gem)。
georgebrock

1
这实际上与文档有关(源文件是XML)。子模块并不是真正的选择,因为我必须在我们现有的基础架构中为其提供充分的依据。
mart1n

52

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

在第一个存储库中(这也可能导出一系列提交,-1如果您只想选择一个提交,请使用):

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

在第二个存储库中:

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

除了使用--relativein之外git format-patch,另一种解决方案是使用-p<n>option in 从补丁程序的路径中git am剥离n目录,如对类似问题回答中所述

也可以git format-patch --relative <committish>不使用--stdout而运行,它将生成一组.patch文件。这些文件可以被直接输送到git amgit am --directory blue/red/ path/to/*.patch


9
这仍然取决于文件名相同的事实,对吗?
mart1n 2015年

3
应该注意的是,该--directory选项似乎要求您指定目录相对于repo根目录的完整路径。--directory=./chdir'd到仓库中的子目录之类的东西将不起作用。
Reid

1
在以下方面使用--3way帮助does not exist in indexgit am --3way --directory (relative-path) (patch)
Brent Bradburn

-k在两个命令中都使用key来不删除提交消息的第一行。
ruvim

使用--3way不仅有助于解决“索引中不存在”错误(如@nobar所指出的),而且还可以使您彻底处理合并冲突。而不是让冲突的文件保持不变,而是添加了一个可以解决的冲突块。
丹尼尔·沃尔夫


5

以@georgebrock的答案为基础,这是我使用的解决方案:

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

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

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

对于每个补丁文件,您都会收到类似“错误:索引中不存在XYZ”的错误。您现在可以手动应用此补丁文件:

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

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

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


1
好的答案,我认为这是任何“非标准”补丁操作的最佳基础。我分三步完成。(1)提交文字 - git format-patch -1 commitA --stdout > thing.diff(2)编辑补丁文件,直到它可以完成我需要的工作为止;(3)要提交的文本, git am --3way thing.diff其优点是您可以接受干净应用的补丁程序的部分,并对不适用的部分使用git标准的冲突解决程序。
我们都是莫妮卡,

2

我了解这两种文件在您的情况下完全相同,因此该补丁很可能会成功。

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

说你修改过的文件A,让我们来分别表示A~1为以前的版本,并且要与应用差异A~1A对文件B

打开一个三向合并工具,例如“超越比较”,左面板的路径为A,中间面板为共同祖先,因此路径为A~1,右面板的路径为B。然后,下图显示应用之间的差异的结果A~1,以A对文件B

下图说明了这个想法。

在此处输入图片说明


0

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

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

无论如何都完成了工作...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.