Git cherry pick vs rebase

Git cherry pick vs rebase,git,version-control,Git,Version Control,我最近开始使用Git 浏览网上的“Git Rebase”部分,我发现了以下内容: 使用rebase命令,您可以进行所有更改 在一个分支上提交,并在另一个分支上重播 (引自:) 我认为这就是git cherry pick的确切定义(在当前签出的分支上重新应用一个提交或一组提交对象) 两者之间有什么区别?樱桃采摘适用于个人提交 当您重新设置基准时,它会将历史上所有的提交应用到缺少的分支头上。自从git cherry pick学会应用多个提交以来,这种区别确实变得有些毫无意义,但这就是所谓的聚合进化;

我最近开始使用Git

浏览网上的“Git Rebase”部分,我发现了以下内容:

使用rebase命令,您可以进行所有更改 在一个分支上提交,并在另一个分支上重播

(引自:)

我认为这就是git cherry pick的确切定义(在当前签出的分支上重新应用一个提交或一组提交对象)

两者之间有什么区别?

樱桃采摘适用于个人提交


当您重新设置基准时,它会将历史上所有的提交应用到缺少的分支头上。

自从git cherry pick学会应用多个提交以来,这种区别确实变得有些毫无意义,但这就是所谓的聚合进化;-)

真正的区别在于创建这两种工具的初衷:

  • git-rebase
    的任务是将开发人员在其私有存储库中针对某个上游分支的版本X创建的一系列更改转发到同一分支的版本Y(Y>X)。这实际上改变了这一系列提交的基础,因此“重新定基”

    (它还允许开发人员将一系列提交移植到任意提交上,但这没有那么明显的用途。)

  • git cherry pick
    用于将有趣的提交从一个开发行带到另一个开发行。一个典型的例子是将一个在不稳定的开发分支上进行的安全修复后移到一个稳定的(维护)分支,在这个分支中,
    合并
    没有任何意义,因为它会带来大量不必要的更改

    自从第一次出现以来,
    git cherry pick
    就能够一次一个地选择多个提交

因此,这两个命令之间最显著的区别可能是它们如何处理所处理的分支:
git cherry pick
通常从其他地方带来提交,并将其应用于当前分支之上,记录新的提交,而
git-rebase
以某种方式接受当前分支并重写其自己的一系列提示提交。是的,这是对
git-rebase
所能做的事情的一个非常简单的描述,但它是有意的,试图让大家理解这个概念

更新以进一步解释正在讨论的使用
git-rebase
的示例

鉴于这种情况,

指出:

然而,还有另一种方法:您可以使用C3中引入的更改补丁,并在C4上重新应用它。在Git中,这称为重定基址。使用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
如下所示:

* 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
  • 运行
    gitmergebase
    查看“实验”和“主控”共享的最后一次提交是什么(换句话说,转移的目的是什么)。我是C2
  • 保存自转移点以来的所有提交;在我们的玩具示例中,它只是C3
  • 将头部倒回(在操作开始运行之前指向“实验”的提示提交)指向“主”的提示-我们正在对其重新定位
  • 尝试按顺序应用每个保存的提交(就像使用
    git apply
    )。在我们的玩具示例中,它只是一个提交,C3。假设它的应用程序将生成一个提交C3’
  • 如果一切顺利,“实验”引用将更新为指向应用上次保存的提交(在本例中为C3)所导致的提交
  • 现在回到你的问题上来。正如您所看到的,从技术上讲,
    git-rebase
    确实将一系列提交从“实验”移植到了“master”的尖端,因此您可以正确地判断在这个过程中确实存在“另一个分支”。但要点是,“实验”中的提示提交最终成为“实验”中的新提示提交,它只是改变了它的基础:


    同样,从技术上讲,您可以看出,
    git-rebase
    在这里包含了来自“master”的某些提交,这是绝对正确的。

    使用cherry-pick,原始提交/分支会保持不变,并创建新的提交。使用rebase,移动整个分支时,分支指向重播的提交

    假设你从以下几点开始:

          A---B---C topic
         /
    D---E---F---G master
    
    重设基础:

    $ git rebase master topic
    
    $ git checkout master -b topic_new
    $ git cherry-pick A^..C
    
    你会得到:

                  A'--B'--C' topic
                 /
    D---E---F---G master
    
          A---B---C topic
         /
    D---E---F---G master
                 \
                  A'--B'--C' topic_new
    
    樱桃采摘:

    $ git rebase master topic
    
    $ git checkout master -b topic_new
    $ git cherry-pick A^..C
    
    你会得到:

                  A'--B'--C' topic
                 /
    D---E---F---G master
    
          A---B---C topic
         /
    D---E---F---G master
                 \
                  A'--B'--C' topic_new
    
    有关git的更多信息,本书提供了大部分内容

    简短回答:

    • git cherry pick更“低级”
    • 因此,它可以模仿git 重基
    以上给出的答案都很好,我只是想举个例子来说明它们之间的相互关系

    不建议用这一系列操作来替换“git-rebase”,它只是“概念证明”,我希望这有助于理解事物是如何工作的

    给定以下玩具库:

    $ 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
    
    比如说,我们在master中有一些非常重要的更改(提交2到5),我们希望将这些更改包含在测试分支1中。通常我们只是切换到一个分支并执行“git rebase master”。但当我们假装只配备了“git cherry pick”时,我们做到了:

    如我们所见,提交#6和#7被应用于7254931(master的提示提交)。头被挪动了
    A---B---C---D---E'---F'---G' master
         \
          E---F---G topic
    
    A---B---C---D---G' master
         \
          E---F---G topic