5

我有两个 git 存储库,它们是彼此的分支,我需要偶尔将提交从一个导入到另一个。

例如:

git-repo1有这个目录结构:

repo1/project1/src

repo1/project2/src

whilegit-repo2具有以下目录结构:

repo2/src/

我想做的是进行一系列提交并仅为更改特定子目录(例如repo1/project1/src)中的文件的提交生成补丁,并忽略所有仅更改其他任何地方的文件的提交。

或者,为所有提交生成补丁,但仅在补丁更改特定目录中的文件时应用补丁。

我需要保留有关提交的元数据,因此玩游戏git diff似乎不是一个可行的选择。

分叉的 git 存储库之间的目录结构不同。

有没有直接的方法来做到这一点?

更新1

在处理不同的目录结构方面,我看到了这个问题(如何将 git 补丁从一个存储库应用到另一个存储库? )。

但是,如果补丁提到修改根本不存在的文件怎么办?我想忽略这些变化。

4

3 回答 3

12

git rev-list --reverseseries-- repo1/project1/src/ \
| xargs -I@ git format-patch --stdout @^! >mystuff.patch

将影响该子目录的一系列提交吐到mystuff.patch

然后,

cat >mystuff.sed <<\EOD
/^(From [0-9a-f]{40}|diff --git )/!{H;$!d}
x
/^From /b
${h;s,.*--,--,;x}
\,^diff[^\n]* [ab]/repo1/project1/src/,!{$!d;x;b}
${p;x}
EOD

sed -Ef mystuff.sed mystuff.patch >justmystuff.patch

将删除该目录之外的所有大块。你可以申请

git am justmystuff.patch

-pn根据--directory=new/path/to需要。

(编辑:EOD --> \EOD 所以上面的猫不会尝试替代)

于 2013-04-12T00:15:29.963 回答
1

如果这两个存储库具有共同的历史(它们都是从同一个存储库派生的,但演变不同),您可以使用cherry-picking有选择地从一个分支导入提交到另一个分支。

创建一个带有两个遥控器的本地存储库(您的两个不同的存储库)

在 repositoryA 中找到涉及某些文件的提交

 $ git checkout repoA/master
 $ git log sub/dir/ectory
 a34256f ...

将这些提交挑选到存储库B 的分支中

 git checkout repoB/master
 git cherry-pick a34256f
于 2013-04-11T21:44:41.193 回答
0

我尝试了在这里和其他答案中找到的几种不同方法,但没有找到适合我的解决方案。这是我发现的。

您可以提供git format-patch一个路径作为参数,以便它只为这些路径创建补丁。

git format-patch HEAD --root $(git rev-list --max-parents=0 HEAD) --stdout -- repo1/project1/src/ > git.patch

该命令git rev-list --max-parents=0 HEAD用于从存储库中获取初始提交 ref

应用补丁可以完成

git am git.patch

在我的例子中,我还想在应用补丁时跳过一个目录级别,因为我正在将整个目录从存储库移动到单独的存储库。git apply被使用的git am有一个标志-p<n>,它从差异路径中删除前导路径组件。默认值为 1,git am -p2 git.patch对我来说也是如此。

于 2021-11-19T09:21:32.110 回答