假设这是我的git历史
Z / A -- C -- D \ / B
我的HEAD目前位于Z
。我想挑选B
和C
。如果我的理解是正确的,我应该这样做:
git cherry-pick B
git cherry-pick C -m 1
git commit --allow-empty
它适用于我的情况,因为C
是一个无操作(因此之后的空提交,我需要提交其他原因),但我想知道-m
之后的参数是什么。以下是我从the docs中读到的内容:
-m parent-number
- 主线家长号
通常你不能挑选合并,因为你不知道合并的哪一边应该被认为是主线。此选项指定主线的父编号(从1开始),并允许cherry-pick重放相对于指定父级的更改。
在我的情况下,C
有两个父母,但我怎么知道哪一个是1和2,更重要的是当我选择1或2时什么时候重要?
答案 0 :(得分:21)
我基于this answer的理解是父1是要合并的分支,父2是要合并的分支。因此,在您的情况下,父级1为A
,父级2为B
。由于樱桃选择实际上是在两次提交之间应用差异,因此您使用-m 1
仅应用B
的更改(因为A
和C
之间的差异包含来自B
的更改。在您的情况下,它可能无关紧要,因为您在A
和C
之间没有提交。
是的,-m 1
就是你想要的,即使A
和C
之间有额外的提交也是如此。
如果您想让新历史看起来更像原始历史,还有另一种方法可以做到这一点:
git cherry-pick B
git checkout Z
git merge --no-ff --no-commit B
git commit --author="Some Dev <someone@example.com>" --date="<commit C author date>"
(如果需要,您可以在挑选之前为B
创建一个新分支。)
这将保留作者信息,应该为您提供如下所示的历史记录:
B'
/ \
Z -- C'
/
A -- C -- D
\ /
B
答案 1 :(得分:2)
我已经赞成Scott Weldon's answer,这是正确的,但我只想添加一个包含父编号的ASCII艺术尝试。给出如下图:
B
/ \
...--A D--...
\ /
C
我们可以告诉节点D
是合并提交,但我们无法判断B
或C
是否是D
的第一个父级。其中一个必须是第一个父母,另一个是第二个。因此,如果我们需要知道,我们必须标记图纸,这需要更多的空间。这是一次这样的尝试。
B
/ \²
...--A D--...
\ /¹
C
我们现在看到,由于某种原因, 1 我绘制了图表&#34;颠倒了#34;:提交C
实际上是{的第一个父{1}},而提交D
是第二个父级。
可以使用较低级别(&#34; plumbing&#34;)命令创建任意合并。特别是,B
只需要按照您给出的顺序获取许多git commit-tree
个参数,并以给定的提交作为其父项进行新的提交。给它一个-p
,它用一个父进行普通提交。不给它-p
个参数,它会进行根提交。给它155个不同的-p
参数(当然所有必须解析为有效的提交ID)并且它会进行一次大规模的章鱼合并提交。
然而,-p
命令总是使用第一个父节点作为当前git merge
进行新的提交(因此当前分支,如果在分支上)。对于标准双父合并,第二个父来自HEAD
,.git/MERGE_HEAD
写入另一个提交ID。如果合并发生冲突,或者最终合并提交延迟了git merge
,则此--no-commit
文件实际上是仅的提交ID可用的地方。
(当MERGE_HEAD
进行章鱼合并时,使用git merge
策略 - 此策略被强制用于此类合并 - 以及多个其他父项,如果存在合并,它将中止并且不留任何痕迹冲突,所以冲突的情况永远不会发生。我没有尝试将-s octopus
与章鱼合并相结合,但是,如果Git允许的话,从逻辑上讲,这将使第2至第N个父母留在--no-commit
中这一点。)
1 固执。