git 樱桃采摘合并提交时的主线父编号

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40148442/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 04:34:26  来源:igfitidea点击:

Mainline parent number when cherry picking merge commits

gitcherry-pickgit-cherry-pick

提问by rink.attendant.6

Suppose this is my git history

假设这是我的 git 历史

  Z
 /
A -- C -- D
 \  /      
  B

My HEAD is currently at Z. I want to cherry-pick Band C. If my understanding is correct, I should do this:

我的 HEAD 目前在Z. 我想挑选BC。如果我的理解是正确的,我应该这样做:

git cherry-pick B
git cherry-pick C -m 1
git commit --allow-empty

It worked in my case because Cis a no-op (hence the empty commit afterwards, I needed the commit for other reasons), but I am wondering what the parameter after -mdoes. Here is what I read from the docs:

它在我的情况下有效,因为它C是空操作(因此之后是空提交,我出于其他原因需要提交),但我想知道后面的参数是做什么的-m。这是我从文档中读到的内容

-m parent-number

--mainline parent-number

Usually you cannot cherry-pick a merge because you do not know which side of the merge should be considered the mainline. This option specifies the parent number (starting from 1) of the mainline and allows cherry-pick to replay the change relative to the specified parent.

-m 父母编号

--mainline 父号

通常你不能挑选合并,因为你不知道合并的哪一侧应该被视为主线。此选项指定主线的父级编号(从 1 开始),并允许cherry-pick 重播相对于指定父级的更改。

In my case, Chas two parents but how do I know which one is 1 and 2, and more importantly when does it matter when I pick 1 or 2?

在我的情况下,C有两个父母,但我怎么知道哪个是 1 和 2,更重要的是,当我选择 1 或 2 时,什么时候重要?

回答by Scott Weldon

My understanding based off this answeris that parent 1 is the branch being merged into, and parent 2 is the branch being merged from. So in your case, parent 1 is A, and parent 2 is B. Since a cherry-pick is really applying the diff between two commits, you use -m 1to apply only the changes from B(because the diff between Aand Ccontains the changes from B). In your case, it probably doesn't matter, since you have no commits between Aand C.

我基于这个答案的理解是父 1 是要合并到的分支,父 2 是要合并的分支。所以在你的情况下,父 1 是A,父 2 是B。由于摘樱桃是真正申请两次提交之间的差异,您使用-m 1仅应用变化从B(因为之间的差异A,并C包含从变化B)。在您的情况下,这可能无关紧要,因为您在A和之间没有提交C

So yes, -m 1is what you want, and that is true even if there were extra commits between Aand C.

所以是的,-m 1这就是你想要的,即使在A和之间有额外的提交也是如此C

If you want to make the new history look a little more like the original history, there's another way to do this:

如果您想让新历史看起来更像原始历史,还有另一种方法可以做到这一点:

git cherry-pick B
git checkout Z
git merge --no-ff --no-commit B
git commit --author="Some Dev <[email protected]>" --date="<commit C author date>"

(If needed, you can create a new branch for Bbefore cherry-picking.)

(如果需要,您可以B在挑选之前创建一个新分支。)

This will retain the author information, should give you a history that looks like this:

这将保留作者信息,应该给你一个看起来像这样的历史:

    B'
   /  \
  Z -- C'
 /
A -- C -- D
 \  /      
  B

回答by torek

I've upvoted Scott Weldon's answer, which is correct, but I just want to add an attempt at ASCII art that includes parent numbering. Given a graph that looks like this:

我赞成Scott Weldon 的回答,这是正确的,但我只想尝试添加包含父编号的 ASCII 艺术。给定一个看起来像这样的图:

       B
      / \
...--A   D--...
      \ /
       C

we can tell that node Dis a merge commit, but we cannot tell whether Bor Cis the first parent of D. One of the two is necessarily the first parent, and the other is the second. So if we need to know, we must label the drawing, which takes more room. Here is one such attempt.

我们可以告诉大家,节点D是一个合并提交,但我们不能告诉是否B或者C是第一父D。两者中的一个必然是第一个父级,另一个是第二个。所以如果我们需要知道,我们必须给图纸贴上标签,这需要更多的空间。这是一种这样的尝试。

         B
       /   
...--A       D--...
       \   /1
         C

We now see that, for some reason,1I have drawn the graph "upside down": that commit Cis in fact the first parent of D, while commit Bis the second parent.

我们现在看到,出于某种原因,1我已经“颠倒”绘制了图形:该提交C实际上是 的第一个父级D,而 commitB是第二个父级。

It's possible to create arbitrary merges using lower level ("plumbing") commands. In particular, git commit-treejust takes however many -parguments you wish to give it, in the order you give them, and makes a new commit with the given commits as its parents. Give it one -pand it makes an ordinary commit with one parent. Give it no -parguments and it makes a root commit. Give it 155 distinct -parguments (all must of course resolve to valid commit IDs) and it makes one massive octopus merge commit.

可以使用较低级别(“管道”)命令创建任意合并。特别是,git commit-tree只需-p按照您提供的顺序接受您希望提供的参数,并以给定的提交作为其父项进行新的提交。给它一个-p,它会与一个父母进行一次普通的提交。不给它任何-p参数,它会进行根提交。给它 155 个不同的-p参数(当然所有参数都必须解析为有效的提交 ID),它会进行一次大规模的章鱼合并提交。

The git mergecommand, however, always makes its new commit with the first parent being the current HEAD(hence the current branch, if on a branch). The second parent, for a standard two-parent merge, comes from .git/MERGE_HEAD, into which git mergewrites the other commit ID. If the merge is conflicted, or the final merge commit is delayed with --no-commit, this MERGE_HEADfile is in fact the onlyplace that commit ID is available.

git merge然而,该命令总是以第一个父级作为当前的HEAD(因此是当前分支,如果在一个分支上)进行新的提交。对于标准的双父合并,第二个父来自.git/MERGE_HEAD,git merge将另一个提交 ID 写入其中。如果合并发生冲突,或者最终的合并提交被延迟了--no-commit,这个MERGE_HEAD文件实际上是提交 ID唯一可用的地方。

(When git mergemakes an octopus merge, using the -s octopusstrategy—this strategy is forced on for such merges—and multiple additional parents, it aborts and leaves no trace at all if there are merge conflicts, so the conflict case never occurs. I have not tried combining --no-commitwith an octopus merge, but that would, logically, leave the 2nd through N'th parents in MERGE_HEAD, if Git allows this at all.)

git merge当做一个章鱼合并时,使用-s octopus策略——这种策略是强制进行这种合并的——和多个额外的父母,如果有合并冲突,它会中止并且根本不留痕迹,所以冲突的情况永远不会发生。我没有尝试过--no-commit与章鱼合并相结合,但从逻辑上讲MERGE_HEAD,如果 Git 允许这样做,那么从逻辑上讲,将第 2 个到第 N 个父母留在 .)



1Obstinacy.

1固执。