Git樱桃采摘vs rebase
我最近开始与Git合作。
在线阅读Git书籍 ( Git book )我在“Git Rebase”部分find了以下内容:
使用rebase命令,您可以获取一个分支上提交的所有更改,并在另一个分支上重播。
(引自: http : //git-scm.com/book/en/Git-Branching-Rebase )
我认为这是git cherry-pick的确切定义(在当前签出的分支上重新提交一个提交或一组提交对象。
我在这里错过了什么?
自从git cherry-pick
学会了能够应用多个提交的时候,这个区别确实变得有点没有实际意义了,但是这被称为融合进化;-)
真正的区别在于创造这两种工具的初衷:
-
git rebase
的任务是将开发人员在其私有存储库中创build的一系列更改转移到同一分支(Y> X)的版本Y,这些更改是针对某个上游分支的版本X创build的。 这有效地改变了这一系列提交的基础,因此“重新定义”。(它也允许开发人员将一系列的提交移植到任意的提交上,但这种用法不太明显)。
-
git cherry-pick
是为了将一个有趣的提交从一个发展线转移到另一个发展线。 一个典型的例子是将在一个不稳定的开发分支上进行的安全修复反向移植到一个稳定(维护)分支,在这个分支中合并是没有意义的,因为它会带来很多不必要的更改。从第一次出现以来,
git cherry-pick
学会了能够一次一个地挑选几个提交。
因此,这两个命令之间最显着的区别在于它们如何处理它们的分支: git cherry-pick
通常会从其他地方提交一个提交,并将其应用于当前分支之上,logging一个新的提交,而git rebase
把你当前的分支,并以这样或那样的方式重写一系列自己的提示提交。 是的,这是对git rebase
可以做的一个严重愚蠢的描述,但是这是有意的,试图让这个总体想法沉入其中。
更新来进一步解释一个正在讨论的使用git rebase
的例子。
鉴于这种情况,
书中指出:
不过,还有另外一种方法:你可以把C3中引入的变化补丁重新应用在C4之上。 在Git中,这被称为rebasing。 使用rebase命令,您可以获取一个分支上提交的所有更改,并在另一个分支上重播。
在这个例子中,你需要运行下面的代码:
$ git checkout experiment $ git rebase master First, rewinding head to replay your work on top of it... Applying: added staged command
这里的“捕捉”就是在这个例子中,“实验”分支(分配的主题)最初是从“主”分支中分出来的,因此它共享了 C0到C2,实际上“实验”是“掌握“,直到并包括C2加上提交C3的顶部。 (这是最简单的情况;当然,“实验”可能包含数十个提交在其原始基础之上的提交)。
现在, git rebase
被告知将“实验”重定位到“master”的当前 git rebase
, git rebase
如下所示:
- 运行
git merge-base
,看看“experiment”和“master”共享的最后一个提交是什么(换句话说,转换的意义是什么)。 这是C2。 - 节省分stream点以来所做的所有提交; 在我们的玩具例子中,这只是C3。
- 在操作开始运行之前,将HEAD(指向“实验”的提示提交)指向“主”的提示 – 我们将重新放在它上面。
- 尝试应用每个保存的提交(就像用
git apply
)。 在我们的玩具例子中,它只是一个提交,C3。 假设它的应用程序将产生一个提交C3'。 - 如果一切顺利,“实验”引用将被更新为指向由应用上次保存的提交(在我们的例子中为C3)导致的提交。
现在回到你的评论。 正如你所看到的,这里从技术上来说, git rebase
确实git rebase
一系列的“实验”提交移植到“主”的提示上,所以你可以正确地说出那里确实存在“另一个分支”。 但要点是“实验”的提示最终成为“实验”中的新提示,只是改变了实验的基础:
再说一遍,从技术上讲,你可以说git rebase
这里包含了来自“master”的某些提交,这是绝对正确的。
用樱桃挑,最初提交/分支粘附和创build新的提交。 通过rebase,整个分支与分支指向重播的提交。
假设你开始:
A---B---C topic / D---E---F---G master
变基:
$ git rebase master topic
你得到:
A'--B'--C' topic / D---E---F---G master
摘樱桃:
$ git checkout master -b topic_new $ git cherry-pick A^..C
你得到:
A---B---C topic / D---E---F---G master \ A'--B'--C' topic_new
更多关于git这本书的信息(http://git-scm.com/book);
樱桃采摘工作的个人承诺 。
当你重新绑定时,它将历史上的所有提交应用到缺less的分支的头部。
简短的回答:
- git cherry-pick更“低级”
- 因此,它可以模拟git rebase
上面给出的答案是好的,我只是想举个例子来试图展示它们之间的相互关系。
我们不build议用这一系列的动作来取代“git rebase”,这只是“概念certificate”,我希望能帮助理解事情的运作方式。
鉴于以下玩具仓库:
$ git log --graph --decorate --all --oneline * 558be99 (test_branch_1) Test commit #7 * 21883bb Test commit #6 | * 7254931 (HEAD -> master) Test commit #5 | * 79fd6cb Test commit #4 | * 48c9b78 Test commit #3 | * da8a50f Test commit #2 |/ * f2fa606 Test commit #1
说,我们有一些非常重要的变化(提交#2到#5)在我们想要包括到我们的分行。 通常我们只需切换到一个分支,并执行“git rebase master”。 但是假装我们只装备了“git cherry-pick”,我们做:
$ git checkout 7254931 # Switch to master (7254931 <-- master <-- HEAD) $ git cherry-pick 21883bb^..558be99 # Apply a range of commits (first commit is included, hence "^")
在所有这些操作之后,我们的提交图如下所示:
* dd0d3b4 (HEAD) Test commit #7 * 8ccc132 Test commit #6 * 7254931 (master) Test commit #5 * 79fd6cb Test commit #4 * 48c9b78 Test commit #3 * da8a50f Test commit #2 | * 558be99 (test_branch_1) Test commit #7 | * 21883bb Test commit #6 |/ * f2fa606 Test commit #1
我们可以看到,#6和#7被提交了7254931(主提示)。 HEAD被动了,并指出了一个实质上是重build分支的提示。 现在我们只需要删除一个旧的分支指针并创build一个新的指针:
$ git branch -D test_branch_1 $ git checkout -b test_branch_1 dd0d3b4
现在test_branch_1根植于最新的主人位置。 完成!