将一个 git 存储库中的补丁导入到另一个存储库中

3
我有两个代码库,它们共享一些代码,但不是全部。偶尔我需要从一个库(上游)中挑选一个提交到另一个库(下游)。在 git loggitk 中浏览可以提供提交哈希值,但我需要一种简单的方法来说“从 ../UpstreamRepo 获取提交 1234abcd 并将其应用到这里”。
在这种特殊情况下,我还想能够仅限于原始文件中已知名称的一个文件来限制新提交。辅助文件(如 NEWS)不适用于此,并且只会导致不必要的合并冲突。这是首选但不是必需的(其他人可能有类似的情况不需要这个)。

请注意,导入过程不必担心合并冲突。如果出现这种情况,我会处理它们(可能使用 git am --abort 并忽略该提交)。它只需要从外部存储库中获取一个单独的提交并将其应用到此处。 - rosuav
如果这是上游和下游仓库,为什么不将一个仓库添加为另一个仓库的远程仓库,然后挑选改动呢? - poke
因为它们之间的连接并不是那么密切。基本上只有一个文件是共享的,而且甚至不是该文件的全部内容。实际上,在我的特定用例中,这个文件甚至没有相同的名称,所以我在过滤器中使用了第三个sed命令-将globals.pike更改为window.pike。 - rosuav
2个回答

5
如果仓库A和B在同一台机器上,或者在可以相互通信的两台机器上。目标是获取B的一个提交并将其应用于A的一个分支。
cd <path_A>
git checkout <branch_A>
git fetch <path_B> <ref_that_contains_commitB>
git cherry-pick <commitB>

如果A和B位于两台无法直接通信的机器上,此方法也适用于A和B位于同一台机器上。
cd <path_B>
git format-patch <commitB> -1
#a xxx.patch is generated
#move this patch to A's workground.
cd <path_A>
git checkout <branch_A>
git am <path_xxx.patch>

另一种你可能想了解的方法。

cd <path_B>
git bundle create B.bundle <ref_that_contains_commitB>
#B.bundle is generated
#move this bundle to A's workground.
cd <path_A>
git checkout <branch_A>
git fetch <path_B.bundle>
git cherry-pick <commitB>

如果A和B无法直接通信,但他们都可以访问仓库C,可能在github或某些公共服务器上。
cd <path_B>
git push <url_C> <ref_that_contains_commitB>:<ref_in_C>
cd <path_A>
git fetch <url_C> <ref_in_C>
git checkout <branch_A>
git cherry-pick <commitB>
git cherry-pick 命令在某些特定情况下可以替换成 git rebase 或者 git merge
更新: 如果提交B修改了一些文件,但是你只想要 file_b 中的改动,
cd <path_B>
git diff <commitB>^ <commitB> -- <file_b>    >   b.patch
#move b.patch to A's workground
cd <path_A>
git checkout <branch_A>
git apply <path_b.patch>
git add .
git commit -m 'xxx'

或者

cd <path_B>
git format-patch <commitB> -1 -- <file_b>
#xxx.patch is generated
#move xxx.patch to A's workground
cd <path_A>
git checkout <branch_A>
git am <path_b.patch>

在所有情况下,我希望有灵活性,能够将提交裁剪到一个文件。 (将编辑问题以澄清此问题。)另外,我不想像第一个库那样获取整个目标存储库。 git format-patch 很接近(也是我在制作新方法之前使用的),但非常笨重。捆绑包很有趣-会研究一下-但看起来也很笨重。 - rosuav

0

我目前最好的解决方案是这样的:

git -C ../UpstreamRepo show 1234abcd|sed '1d; 2s/^Author/From/'|git am -

管道中的sed有两个原因:首先,git show将提交哈希放在第一行,而git am不接受;其次,第二行上的Author:不被git am识别为作者标记。所以它有点丑陋。

所有通常的git show子命令都可用,包括将其限制为特定文件,并使用分支相对提交命名而不是抓取特定哈希。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接