Chr*_*ris 27 git cherry-pick git-cherry-pick
在正常的Git合并冲突中,三向合并的三个版本的文件大致如下:
当一个Git樱桃挑选产生合并冲突时,没有共同的祖先,正确地说,那么这些东西是如何确定的?关于rebase也可以这样说.
Chr*_*ris 38
摘樱桃
除非我误导自己,否则如果你做"git cherry-pick <commit C>",那么你得到:
如果不能立即清楚为什么BASE应该是C ^,请参阅下面的"为什么"部分.
与此同时,让我们举一个例子,看看BASE 可以但往往不会成为樱桃选择中的共同祖先.假设提交图看起来像这样
E <-- master
|
D
| C <-- foo_feature(*)
|/
B
|
A
Run Code Online (Sandbox Code Playgroud)
你在分支foo_feature(因此是星号).如果你做"git cherry-pick <commit D>",那么那个樱桃选择的BASE将提交B,它是C和D的共同祖先.(C将是LOCAL,D将是REMOTE.)但是,如果你改为"git cherry-pick <commit E>,那么BASE将提交D.(C将是LOCAL,E将是REMOTE.)
变基
对于背景上下文,rebase大致是迭代的挑选.特别是,在master之上重新定位主题(即"git checkout topic; git rebase master")意味着:
git checkout master # switch to master's HEAD commit
git checkout -b topic_rebased # create new branch rooted there
for each commit C in master..topic # for each topic commit not already in master...
git cherry-pick C # bring it over to the new branch
finally, forget what "topic" used to mean and now defined "topic" as the HEAD of topic_rebased.
Run Code Online (Sandbox Code Playgroud)
在此过程中应用的标签是正常樱桃挑选规则的扩展:
如果你想避免混淆,这意味着需要记住LOCAL与REMOTE的关系:
即使您在启动rebase时处于分支主题,LOCAL也不会在 rebase正在进行时引用主题分支上的提交.相反,LOCAL始终引用正在创建的新分支上的提交(topic_rebased).
(如果没有记住这一点,那么在一次令人讨厌的合并期间,人们可能会开始问自己,"等等,为什么说这些是局部变化?我发誓他们是对主人做出的改变,而不是在我的分支上.")
更具体地说,这是一个例子:
假设我们已提交图表
D <-- foo_feature(*)
|
| C <-- master
B |
|/
|
A
Run Code Online (Sandbox Code Playgroud)
我们目前在分支foo_feature上(用"*"表示).如果我们运行"git rebase master",则rebase将分两步进行:
首先,B的变化将在C之上重放.在此期间,C是LOCAL,B是REMOTE,A是BASE.请注意,A是B和C的真正共同祖先.在第一步之后,您有一个大致相同的图形:
B' <-- foo_feature
D |
| |
| C <-- master
B /
|/
|
A
Run Code Online (Sandbox Code Playgroud)
(在现实生活中,B和D可能已经在树上被修剪掉了,但是我将它们留在这里,以便更容易发现任何潜在的共同祖先.)
其次,D的变化将在B'之上重播.在此期间,B'是LOCAL,D是REMOTE,B是BASE.请注意,B不是任何事物的相关共同祖先.(例如,它不是当前LOCAL和REMOTE,B'和D的共同祖先.它不是原始分支头的共同祖先,C和D).在这一步之后,你有一个大致如此的分支:
D' <-- foo_feature
|
B'
D |
| |
| C <-- master
B /
|/
|
A
Run Code Online (Sandbox Code Playgroud)
为了完整性,请注意在图表中删除rebase B和D的末尾,产生:
D' <-- foo_feature
|
B'
|
C <-- master
|
A
Run Code Online (Sandbox Code Playgroud)
为什么BASE定义为它?
如上所述,对于cherry-pick和rebase,BASE都是提交C的父(C ^).在一般情况下,C ^不是一个共同的祖先,所以为什么称它为BASE ?(在正常的合并中,BASE 是一个共同的祖先.而git在合并方面的成功部分归功于它能够找到一个好的共同祖先.)
实质上,人们通过普通的三向合并算法来实现"补丁"功能.特别是你得到这些"不完整"的属性: