Git合并了来自cherry命令的提交范围

时间:2017-01-25 23:15:15

标签: git git-merge

说我有两个分支,A& B.我跑的时候

git cherry -v A B

我将获得分支B中存在但在分支A中不存在的提交列表。在这个例子中,假设列出了50个提交:

+ 53458a1a commit 1
+ de6e9b10 commit 2
+ 683f3ef2 commit 3
+ a9e8e23d commit 4
...
+ 127197fb commit 50

有没有办法只将前面列出的四个提交合并到分支A中,而不进行挑选或重新定位?

在分支A上,我尝试过:

git merge a9e8e23d

但这只能让我获得第四次提交,并且它不包括提交1-3。

我也尝试在commit 4创建一个本地分支:

git branch tmp a9e8e23d

但是分支tmp不包含提交1-3。

我通过运行验证分支是否包含提交:

git branch --contains de6e9b10 

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

  

有没有办法只将前面列出的四个提交合并到分支A中,而不进行挑选或重新定位?

如果您想在合并中进行特定提交,则必须使用cherry-pick,但cherry-pick的优点是您可以提供范围以便获取多个提交。

例如,获取前4个提交

# The .. marks the commits range.
git cherry-pick 53458a1a..a9e8e23d

答案 1 :(得分:0)

TL; DR:"是的,如果满足某些非常常见的约束条件。"

  

......当我跑步时

git cherry -v A B
     

我将获得分支B中存在但在分支A中不存在的提交列表。

不完全:您在B中获得所有非合并提交的列表,这些提交不在A中,标记为前缀。如果+中的提交在B中没有相应的提交,则标记为B..A,如果- 中的提交,则B >在B..A中有相应的提交(由git patch-id确定)。

如果您只想要B中不在A中的提交列表,无论修补程序ID是否等效,您都可以使用以下命令:

git rev-list A..B

这些都是没有前缀的,而包括合并提交(尽管您可以在内部添加--max-parents=1--no-merges,以排除合并)。

  

有没有办法只将前面列出的四个提交合并到分支A中,而不进行挑选或重新定位?

有时,但并非总是如此。

请注意,您已经明确询问了合并这些提交。你还说前四个。这里有许多潜在的问题,但让我们先来看一下合并提交和/或分支的含义。

要做的第一件事是绘制(部分)提交图:

git cherry

这里我们有两个分支名称 A1--A2--A3 <-- A / ...--o--* \ B1--B2--B3--B4 <-- B A,其中三个提交在分支B上不在A上,四个提交在B上那些不在B中。 两个分支上至少有两个提交,以标记为A的提交结束,并包括所有早期提交。

使用*,您会看到这四个git cherry -v A B提交(包含缩短的哈希值和主题行),前缀为B+

要将整个分支-合并到分支B,您可以执行以下操作:

A

在找到合并基础提交git checkout A; git merge B 之后,尝试将所有*提交中的所有更改与来自所有A提交的所有更改组合在一起,并创建一个B上的新合并提交:

A

请注意,这已经合并了提交 A1--A2--A3------M <-- A / / ...--o--* / \ / B1--B2--B3--B4 <-- B (分支A3的提示,您在A之后)提交git checkout A(分支的提示{{1} }})。这是B4的工作方式,当给出一个名称时:它找到分支提示提交,并与当前提交合并 - 无论你已经签出了什么

从那里提交的提交。例如,要合并提交B,您将:

git merge

,并提供:

B4

甚至可以合并B3(包括git checkout B; git merge <hash-id-of-B3> ),或仅 A1--A2--A3--M <-- A / / ...--o--* / \ / B1--B2--B3--B4 <-- B (因为分支在B2加入, 包括B1),例如:

B1

可以合并*而不包括B1 A1--A2--A3--M <-- A / / ...--o--* / \ / ----B1--B2--B3--B4 <-- B ,或B3B1合并例如,但不是B2。一旦您进行合并,该图本身就会自动包含所有之前的提交。 (这是因为图形实际上是通过读取每个提交来构建的。读取合并提交B3告诉Git将B1视为第一个父级,以及B2提交它作为第二个然后,它会自行提交MA3来回顾B和之前的A3提交,依此类推。

现在,因为Bn省略了合并提交,如果我们刚刚绘制的图表过于简单,我们就会遇到麻烦。例如,假设图形实际上如下所示:

A2

如果我们运行A,我们会再次看到四次git cherry次提交。我们没有看到提交 A1--A2--A3 <-- A / ...--o--* B2 \ / \ B1 B4--B5 <-- B \ / B3 ,因为它是git cherry -v A BB的合并。我们看到一些顺序;我们也会回复此问题 - B4B3B2B1

我们假设您选择B2进行合并。除非我将图形的下半部分颠倒过来,否则这很难画出来,所以我会这样做:

B3

查看结果:我们已合并B5B3,但未合并 A1--A2--A3--M <-- A / / ...--o--* B3 \ / \ -------B1 B4--B5 <-- B \ / B2 。这可能不是你想要的。我们可以合并B1,或者我们可以合并B3以获得B2的合并结果(这是B2中合并的内容)以引入所有内容B4。但B2+B3输出中甚至没有列出B4

现在我们遇到另一个问题。显示的B1-B2-B3B4git cherryB1的顺序是什么? 应该显示的顺序是什么?如果Git向您显示B2然后B3然后B5以及B1 B3,您就会得到您期望的结果。但是,如果它显示B2然后git merge然后B3以及B1,则会得到您 期望的内容:{ {1}}似乎不见了!

B2未指定显示这些提交的实际顺序。如果您使用B3代替git merge B3,则可以使用B2git cherrygit rev-list来控制订单(实际上您只需要git cherry })。您仍然会遇到合并的潜在问题,因此您可能希望检查(例如,使用--topo-order,是否已备份任何合并,或--date-order--author-date-order中是否存在任何合并1}}(无论你是否计划在该点之前或之后合并)。

--topo-order限制确保子提交在父提交之前提交,即列表以git rev-list --count顺序进行。添加git rev-list --merges --count会颠倒此顺序,如果没有合并 - 就像上面的四个commit-long变体一样 - 以从左到右的顺序获取提交,这样您就可以确定哪些修订提供了哪些历史。

在我的测试中,A..B 似乎以反向拓扑顺序列出 - 但文档中没有任何内容可以保证这一点,并且快速查看源代码,也没有任何来源。如上所述,您还可以获得一个标记,其中“提交”位于上游,由相同的修补程序ID&#34;确定,但这应该是无害的。所以唯一真正的限制是图表强加的是什么,即你的&#34;前N是否提交&#34;确实是第一次 N提交:没有排序问题,没有后​​续合并的分支没有重新组合它们。

底线

如果您的--topo-order输出(跳过合并)首先没有合并要跳过,输出以反向拓扑顺序出现,然后你一定很好。两者通常都是正确的 - 通常你会在一个简单的分支B&#34;上运行它。没有合并,通常没有问题,提交以错误的顺序显示。

在Git的其他版本中,我看到提交以不同的顺序出现,并且在当前(Git 2.10 / 2.11)文档中没有描述为&#34;总是以反向拓扑顺序和&#34; #34 ;.当然,您可能正在运行包含内部分支的分支上。所以在这种情况下,答案是否定的。