git:将在一个存储库中提交所引起的更改应用于另一个存储库


115

我有一个repo1repo2本地机器上。它们非常相似,但是后者是某种其他分支(repo1不再保留)。

/path/to/repo1 $ git log HEAD~5..HEAD~4
<some_sha> Add: Introduce feature X

如何申请通过提交所做的更改<some_sha>repo1repo2

我需要准备一些补丁,还是可以cherry-pick在回购之间做一些补丁?

除了提交范围之外,该如何做?


2
您不能只从repo1拉到repo2吗?
zwol10年

对于您正在寻找应用更改到了在仓库的一个移动的文件或文件稍微更具体的情况,请看这里:stackoverflow.com/questions/3491270/...
布拉汉姆斯奈德

Answers:


31

作为一种技巧,您可以尝试修改配方以比较GitTips页面上两个不同存储库中的提交,即:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects \
git cherry-pick $(git --git-dir=../repo/.git rev-parse --verify <commit>)

../repo另一个存储库的路径在哪里。

使用现代的Git,您可以在cherry-pick中使用多个修订版本和修订范围。

$(git --git-dir=../repo/.git rev-parse --verify <commit>) 是在这里翻译<commit>(例如HEAD,或v0.2,或master~2,其中是在从复制第二存储库值)转换成提交的SHA-1的标识符。如果您知道要选择的SHA-1变更,则没有必要。

但是请注意,Git可以跳过从源存储库复制对象的步骤,因为它不知道备用对象存储库只是一个操作的临时对象。您可能需要使用以下命令从第二个存储库复制对象:

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects git repack -a -d -f

这会将从第二个存储库借来的那些对象放入原始存储库中

未经测试。


一个不太好用的解决方案是遵循knittl答案

  • 转到要从中复制提交的第二个存储库,并使用所需的提交生成补丁 git format-patch
  • (可选)将补丁(0001- *等)复制到您的存储库
  • 使用git am --3way应用补丁

1
效果不错。如果您在提交时遇到问题,请执行git reset HEAD; git add。'。
gumik

5
这很棒-您将如何进行一系列提交?只是sha1 ... sha2?
hvgotcodes 2013年

我也得到了,fatal: unable to read tree ...但是在git reset HEAD^一切正常之后
jmarceli 2014年

@hvgotcodes简单地通过将范围传递给我为它工作,<commit>但该rev-parse --verify命令不喜欢它,因为它仅接受单个提交值。但是当cherry-pick接受单个和范围提交值时,我问:为什么rev-parse需要?
Chuim 2015年

1
@Chuim:git rev-parse如果你想引用一个在其他存储库,例如它的基于REF-名称提交需要masterHEAD^^或类似的东西; rev-parse将其转换为通用SHA-1标识符。
JakubNarębski2015年

207

您可能想要使用该修补程序git format-patch,然后git am将其应用于存储库。

/path/to/1 $ git format-patch sha1^..sha1
/path/to/1 $ cd /path/to/2
/path/to/2 $ git am -3 /path/to/1/0001-…-….patch

或者,一行:

/path/to/2 $ git --git-dir=/path/to/1/.git format-patch --stdout sha1^..sha1 | git am -3

9
事实证明,此解决方案比使用直接挑选樱桃的公认答案更为简单和安全GIT_ALTERNATE_OBJECT_DIRECTORIES(因为这样做会破坏我的存储库)。
Chuim 2015年

2
发生冲突时,它将无法正常工作,因为它无法在另一个分支上找到提交。
罗杰·法尔(Roger Far)

2
添加--ignore-whitespacegit am命令可以解决任何冲突,并且避免执行三向合并
休斯(Hugheth)

97

cherry-pick如果将第二个存储库添加为第一个存储库的远程(然后是fetch),则可以这样做。


11
这实际上是正确的方法。
威伯特

5
对我来说,这也感觉正确。而且我只是使用它,它对我来说效果很好。
里奇·尼尔森

10
我宁愿说:先git fetch [remote-name]在第二个回购中再执行git cherry-pick [sha1]

5
谢谢,这种方法对我很有用。由于第二个存储库也是本地的,因此在将其添加为远程文件时只需要使用文件URI。
palimpsestor 2015年

2
就我而言,我有一个巨大的远程git存储库的两个克隆(以允许并行工作),这意味着它的所有历史记录都已下载并在我的HD中存储了两次。如果我还必须将彼此添加为彼此的远程对象,那将创建同一历史记录的两个额外副本,并且可能需要在它们之间进行同步,然后我才能进行cherry-pick。因此,即使感觉上像是“正确”的方式,也不总是最实用。
Chuim 2015年

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.