我怎样才能追溯合并git分支?

时间:2016-04-13 08:46:53

标签: git

注意这不是标记的副本 - 事实证明我没有想要cherry-pick,而是merge。因此,我认为应该将其视为自己的问题,以防其他人遇到同样的情况。

我有一个包含一系列提交的develop分支。当功能集完成时,我会定期将此分支合并到master。在过去的某个时刻,我意识到我应该合并develop分支。例如:

A
 \     Merge
  \      |
   B--C--D--E--F

Amaster上的最后一次提交,Bdevelop分支的第一次提交。

我希望将提交BCD合并到master,但我只知道如何合并整个分支。最终,提交EF将合并,但现在我需要合并到D

A----------D
 \        /
  \      /
   B--C--D--E--F

我知道我可以为一次提交执行以下操作,但我该如何处理范围?

$ git checkout master
$ git cherry-pick B

注意未来的自我:记得始终创建一个功能分支!

2 个答案:

答案 0 :(得分:3)

首先,关于樱桃挑选的快速评论:樱桃挑选和合并是非常不同的(稍微更多)。

合并特定提交

现在,合并。通常我们会像这样描述合并序列:

$ git checkout master
$ git merge sidebranch

如果自动合并进展顺利,git将在当前分支上创建一个新的合并提交 - 在这种情况下,在master上 - 其每日“第一个”父级是上一个提示当前分支,其第二个父是我们告诉git合并的提交。

第二个父级的事实是使其成为合并提交的原因。以图解方式得到:

A <----------- M  <-- master
 \           /
  B <- C <- D     <-- sidebranch

其中M有两个父母AD。名称master现在指向新的合并提交M,而名称sidebranch未受影响且仍指向D

git mergesidebranch参数的作用是两件事,其中只有一件非常重要:

  • 它将它转换为特定的提交并使用该提交进行合并;和
  • 它将参数名称放入默认提交消息(merge branch sidebranchmerge branch sidebranch into foo,只有当前分支且名称为{{1}时才出现into foo }})。

第二项并不重要,至少不是git:git只显示提交消息,它永远不会依赖于消息。如果您选择编辑邮件,则可以说出其他内容。

所有这一切的重点在于,您可以识别任何提交,而不仅仅是分支的提示,而git可以合并它。因此,如果master继续进行,就像你的情况一样,但你具体指定了提交sidebranch,那么你得到:

D

这就是你想要的。然而,Git的自动生成的合并提交消息文本是A <----------- M <-- master \ / B <- C <- D <- E <- F <-- sidebranch ,它可能不是你想要的。这很容易解决:只需将其编辑为merge commit <hash>

(为了完成合并本身,git执行通常的three-way merge,找到合并基础,并针对要合并的两个提交区分该提交。)

关于樱桃挑选的其余部分

merge和cherry-pick之间的主要区别不在于合并本身(你可以挑选一系列提交,甚至不通过将merge branch sidebranch添加到cherry-pick中而不提交每个提交命令:结果是git称之为“squash merge”,除非效率低得多,你可能需要多次以这种方式解决相同的冲突)。相反,它是最终提交不是合并提交,即没有第二个父级。

这意味着生成的提交图形是不同的,即使源代码更改是相同的(就像它们用于压缩“合并”)。这没有立即效果,但这意味着未来合并将不知道已经发生了挑选,并且必须努力跳过它(这可能或者可能不会成功)。记录第二个父级为git提供了为后面的合并找到正确的新合并基础所需的所有信息。

作为一个例子,考虑通过将-n的效果复制到B+C+D来获得的“合并”:

master

此处A <-------- S <-- master \ B <- C <- D <- E <- F <-- sidebranch 是通过“我们在S中做了什么”(通过差异B vs A)并将其应用于{{1然后,取“我们在B中做了什么”(差异A vs C)并应用它,最后,取“我们在B中所做的”和应用它。到目前为止一切都很好 - 我们在C中所做的事情显然必须干净地应用于D,依此类推。

问题发生在(或者可能是“if”)我们稍后再次将B合并到A时。 Git将搜索合并基础并发现它是提交sidebranch,因此它将比较masterAAS可能然后能够自动构建正确的树,具体取决于AF与我们之前选择的更改的变化。但是,如果我们已合并,则git会将E视为合并基础,并比较F - vs - D以获取要引入D的新项目。

答案 1 :(得分:0)

尝试这些命令。

git checkout master
git cherry-pick b^..d

Git 1.7.2引入了一系列提交的能力。

  

git cherry-pick“学会了选择一系列提交(例如”cherry-pick A..B“和”cherry-pick --stdin“),”git revert“也是如此;这些不支持更好但是,测序控制“rebase [-i]”有。