这个问题源于一个令人讨厌的小合并冲突,当我不小心从我的跟踪分支机构挑选到我的跟踪分支而不是重新调整它时,我进入了这个冲突。修复它很容易,但仍然试图解决为什么它首先发布。
假设我有以下分支(tracking
基于tracked
),一系列提交,括号中有哈希,箭头指向父提交。
tracked: a(123) <- b(234) <- c(345)
tracking: a(123) <- b(234) <- c(345)
假设提交标识d
的新提交456
进入tracked
,以便分支的状态如下:
tracked: a(123) <- b(234) <- c(345) <- d(456)
tracking: a(123) <- b(234) <- c(345)
我现在cherry-pick
456
进入tracking
,导致以下跟踪状态:
tracking: a(123) <- b(234) <- c(345) <- d(somethingnot456)
但是,如果我只是执行git rebase tracked
,那本来应该是:
tracking: a(123) <- b(234) <- c(345) <- d(456)
那么为什么上面的ID不同?
我见过很多关于rebase
vs cherry-pick
的问题,但我没有设法找到这个具体问题的答案。感谢。
答案 0 :(得分:4)
Rebase和(重复)樱桃选择本质上是相同的,但它们不是100%完全相同的东西。在这种特殊情况下,关键是被复制的东西,这一点都没有。
让我以我喜欢表达Git图形片段的方式重绘您的示例。而不是:
tracked: a(123) <- b(234) <- c(345)
tracking: a(123) <- b(234) <- c(345)
让我们把它画成:
A(123) <- B(234) <- C(345) <-- tracking, tracked
因为毕竟每次提交都是唯一的:只有一份A
,一份B
,一份C
,很快就会成为{{1}之一}}。同时,两个标签(D
和tracking
)都指向提交tracked
,其哈希值为C
。
现在您将新提交345whatever
添加到D(456)
(因此tracked
仍然指向tracking
:
C(345)
A(123) <- B(234) <- C(345) <-- tracking
\
D(456) <-- tracked
的作用本质上是:
git cherry-pick <commit>
vs D
)C
)上,应用相同的更改,这当然就是你以前见过的。您当前的分支(tracking
)获取新提交tracking
:D'
的副本,但编号不同。
D
)具有的所有提交的列表,而tracking
分支(<upstream>
)则没有。具体来说,这些是tracked
将列出的提交:
git rev-list
没有这样的提交,从图纸中很容易看出。我们甚至不需要哈希:
$ git rev-list tracked..tracking
$
从A <- B <- C <-- tracking
\
D <-- tracked
开始,我们按照标记提交的箭头向左移动,但是从tracking
开始,我们按照箭头和 un 标记再次向左移动提交。由于tracked
会返回D
,因此会显示所有内容,而我们根本不会复制任何内容。
如果我们在C
上提交了未跟踪的:
tracking
然后rebase将复制A--B--C--E <-- tracking
\
D <-- tracked
,进行新的(不同的ID)提交E
。 E'
的副本将在E
之后发布,如下所示:
D
完成所有复制A--B--C--E <-- tracking
\
D <-- tracked
\
E' [rebase in progress]
后,如果没有要复制的内容,则会记录它在git rebase
停止的位置;在D
,或者甚至是E'
或F'
或其他任何内容,如果 提交要复制 - 然后它剥离旧的分支标签({{1} })关闭并粘贴在新点上:
G'
如果没有tracking
要复制,我们会改为:
A--B--C--E [abandoned]
\
D <-- tracked
\
E' <-- tracking
,即两个分支标签现在都指向提交E
,而根本没有复制。 (没有理由在图表中保留一点点下行,并且没有放弃放弃的提交A--B--C
\
D <-- tracked, tracking
不放弃D
,因为E
是可以找到的来自C
。)
答案 1 :(得分:1)
git rebase
将在另一个基本提示之上重新提交提交#34;而git cherry-pick
将&#34;应用某些现有提交引入的更改&#34;。
换句话说,变基将直接在当前分支上应用提交,而樱桃挑选会将提交中的更改应用到当前分支(然后制作一个新的提交)。
rebase文档甚至在概要后明确说明了这一点:
如果已指定, git rebase 将在执行任何其他操作之前执行自动
git checkout <branch>
。否则它将保留在当前分支上。
因此,在使用git rebase tracked
时,您基本上只是执行了git checkout tracked
并快速转发了您的tracking
分支...