我使用两个 git 存储库,其中一个包含另一个的一些代码,但位于不同的路径下。
例如仓库 A 有一个目录 src/packages/my-pkg
,并且 Repo B 有一个目录 different-path/my-pkg
,并且两个目录具有(大部分)相同的内容。
我想自动化将功能/错误修复从一个复制到另一个的过程。所以如果一个文件 src/packages/my-pkg/some-component/index.js
已修改,可将更改复制到different-path/my-pkg/some-component/index.js
在另一个仓库中。然而,index.js
存储库之间可能略有不同,因此需要容忍这一点并尽可能多地应用差异。
这是我迄今为止提出的流程:
# Get a diff containing the changes in a feature branch
cd repoA
git diff master new-feature-branch > ../feature.diff
# Convert the file paths in the diff to the other repo's structure
sed -i "" 's+src/packages/my-pkg+different-path/my-pkg+g' ../feature.diff
# Apply to the other repo
cd ../repoB
git apply --reject ../feature.diff # --reject option tells git to apply the changes it can, and put the rest in .rej files
这在一定程度上有效,但对存储库之间的差异非常敏感。例如,当尝试将此更改从存储库 A 应用于存储库 B 时:
--- a/different-path/my-pkg/title-bar/view.js
+++ b/different-path/my-pkg/title-bar/view.js
@@ -95,6 +95,7 @@ export default class TitleBar extends Component<Props> {
</span>
</div>
);
+ // A new comment
case READONLY:
return (
<Title>
如果 Repo B 中的任何上下文行已更改(例如,将 prop 添加到 <Title>
),git 将无法匹配该位置,并且差异将不适用。
我认为,如果 git 可以在 Repo A 中的文件的旧/新版本和 Repo B 中的文件之间进行 3 路 merge ,它可以更好地确定在哪里插入更改。但我不知道如何实现这一点。
有人知道如何解决这个问题吗?
(显然,理想的解决方案是将共享代码提取到可重用的模块中。但它很大,并且存在许多细小的差异,因此所涉及的工作量使其无法启动。)
最佳答案
有两种方法可以增加仍然应用不太合适的补丁的机会:
第一种形式
git apply -3 that.diff
使用 merge 机制来应用补丁并可能产生冲突,但在其他方面非常擅长应用上下文行不匹配的补丁。 git apply
使用补丁中记录的 blob ID;为此,需要将生成补丁的仓库添加为远程仓库。
第二种形式
git apply -C2 that.diff
减少必须匹配的上下文行数。如果上下文不明确,这也增加了补丁应用在错误位置的危险。可以将上下文减少到零行,但如果补丁仅添加文本,则这是非常危险的,因为补丁应用程序剩下的唯一提示是行号,并且它们通常是不精确的提示。如果补丁包含已删除的行,零上下文行问题就不那么大了,因为它们确实保留为上下文。
编辑:为了解释路径名的更改,-p<n>
可用于从补丁中记录的路径中剥离多个目录,以及 --directory=foo/bar
可以用来替代不同的路径。这假设至少文件名保持不变。
关于git - 如何将 git diff 应用于略有不同的存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64798656/