【问题标题】:What does cherry-picking a commit with Git mean?用 Git 挑选提交是什么意思?
【发布时间】:2018-03-20 20:38:21
【问题描述】:

最近,有人要求我 cherry-pick 提交。

那么在 git 中挑选提交是什么意思?你是怎么做到的?

【问题讨论】:

  • 不是合并,而是选择从一个分支重新提交到目标分支(例如:master)更容易。
  • 有人能说吗?:“Cherry-picking 提交意味着在 HEAD 上创建一个临时分支,将该提交的差异合并到其中,然后快进 HEAD。”或者简单地说:“合并单个提交”。

标签: git cherry-pick git-cherry-pick


【解决方案1】:

Git 中的樱桃采摘意味着从一个分支中选择一个提交并将其应用到另一个分支。

这与mergerebase 等其他方式形成对比,后者通常将许多提交应用到另一个分支。

  1. 确保您位于要将提交应用到的分支上。

     git switch master
    
  2. 执行以下操作:

     git cherry-pick <commit-hash>
    

注:

  1. 如果你从公共分支中挑选,你应该考虑使用

     git cherry-pick -x <commit-hash>
    

    这将生成一个标准化的提交消息。这样,您(和您的同事)仍然可以跟踪提交的来源,并可能避免将来发生合并冲突。

  2. 如果您在提交中附加了注释,则它们不会遵循樱桃选择。要将它们也带过来,您必须使用:

     git notes copy <from> <to>
    

其他链接:

【讨论】:

  • 真的有必要摘樱桃吗?混合重置或软重置不会做类似的工作吗?
  • git push 是对 master 进行更改的最后一步
  • 仅供参考:提交在语义上包含当时工作树的所有文件(以及上一次提交的提交哈希),因此您不是将整个提交应用于另一个提交,而是将更改应用于对上一次提交所做的提交"cherry-pick commit applies the changes introduced by the named commit on the current branch" 大多数人倾向于将提交视为更改(就像 svn 是 iirc),但事实并非如此,每个提交都指的是完整的工作树。尽管在这种情况下这并没有什么不同,但它可以帮助理解 git 为何如此工作。
  • @Zitrax 与提交消息的注释不同吗?我的单个 git cherry-pick 命令也能够带来我的提交消息。你在说别的吗?我根本不需要运行git notes 命令来完成它。
  • @RBT 是的,注释与提交消息不同,提交消息跟在cherry-pick 上的提交之后。见git-scm.com/docs/git-notes
【解决方案2】:

此引用摘自:Version Control with Git

使用 git cherry-pick 命令 git cherry-pick commit 应用 由当前分支上的命名提交引入的更改。它会 引入一个新的、不同的提交。 严格来说,使用 git cherry-pick 不会更改存储库中的现有历史记录; 相反,它增加了历史。与其他 Git 操作一样 通过应用差异的过程引入更改,您可能需要 解决冲突以完全应用来自给定提交的更改。 命令 git cherry-pick 通常用于引入特定的 从存储库中的一个分支提交到另一个分支。一种 常见用途是从维护中转发或反向端口提交 分支到开发分支。

$ git checkout rel_2.3
$ git cherry-pick dev~2 # commit F, below

之前:

之后:

另外,这里有一个非常好的视频教程:Youtube: Introduction to Git cherry-pick

【讨论】:

  • 当在某个分支 (b1) 上进行精选提交并随后交付给 master 时。如果分支 b1(最初从中选择提交)也尝试交付给 master。冲突如何?是否得到照顾或它是如何工作的?
  • @parasrish 是的,他们已经对您之前的合并进行了处理。因此,您确实从 (b1) 分支更改了 a、b、c、d。你樱桃只选了“c”。那么将来一旦你从(b1)合并到master,由于“c”的变化是相同的,它只会合并a,b,d并保持“c”的变化。但是,如果您回滚合并,那么您将返回带有“c”的更改。您需要单独回滚它们。
  • 需要强调的是:在给出的示例中,只有差值 (F - E) 应用于 Z。这是一个狭义的情况。 Cherry-pick 可用于应用多个提交的差异,例如,两个非相邻提交之间的所有差异。例如,从上面开始,(F - E)、(E - D)、(D - C) 和 (C - B)。这相当于应用差异 (F - B)。
  • 另外,如果选定的提交(示例中为 F)有多个直接前任,会发生什么情况?
  • @j2emanue 换句话说,cherry-pick 只会接受 last-commit 的更改。如果您提交 3 次不同的时间,并且如果您选择最后一次,则不会在第一次和第二次提交时进行更改。合并命令将接受您的所有更改并应用到您的目标(主)分支。
【解决方案3】:

Git 中的 Cherry Picking 旨在将一些提交从一个分支应用到另一个分支。如果你可以这样做。犯了一个错误并将更改提交到错误的分支,但不想合并整个分支。你可以只是例如。恢复提交并在另一个分支上挑选它。

要使用它,您只需要git cherry-pick hash,其中hash 是来自其他分支的提交哈希。

完整流程见:http://technosophos.com/2009/12/04/git-cherry-picking-move-small-code-patches-across-branches.html

【讨论】:

    【解决方案4】:

    情况的简短示例,当您需要樱桃采摘时

    考虑以下场景。你有两个分支。

    a) release1 - 这个分支是给你的客户的,但是有 还有一些bug有待修复。

    b) ma​​ster - 经典的 master 分支,例如,您可以在其中添加 release2 的功能。

    现在:您在 release1 中修复了一些问题。当然,您也需要在 ma​​ster 中进行此修复。这是樱桃采摘的典型用例。因此,在这种情况下,cherry pick 意味着您从 release1 分支获取提交并将其包含到 ma​​ster 分支中。

    【讨论】:

    • 您可能只需要另一种方式。您修复了 master 中的一个错误,您应该挑选它来发布 1。它们也可能是存储库而不是分支
    • 为什么不用merge呢?
    • 我会:创建分支发布,在分支中修复它,在发布中合并分支,在 master 中合并发布。
    • 我认为这个答案需要解释分支之间的关系:如果release1预计以后会合并到master中,那么cherry-pick(恕我直言)可能没有意义。我猜你还想在挑选完樱桃后重新调整master1
    【解决方案5】:

    我准备了 cherry-pick 所做的分步插图 - 以及这些插图的动画(接近尾声)。

    1. 樱桃采摘前
      (我们将从分支feature 中对提交L 进行cherry-pick):

    1. 启动命令git cherry-pick feature~2
      feature~2
      feature 之前的第二次nd 提交,即提交L):

    1. 执行命令后(git cherry-pick feature~2):

    同样的动画:


    注意:

    提交L'从用户的角度来看(提交=快照)提交L 的精确副本。

    技术上(内部),这是一个新的、不同的提交(因为例如L 包含指向K(作为其父级)的指针,而L' 包含指向@987654341 的指针@)。

    【讨论】:

    • 这是否意味着,L' 将是 N -> M -> L 在分支 master 上?否则它将专门在 master 分支上带来提交 L
    • @PriyankThakkar,是的,仅限 L,没有别的(从图片/动画中可以看到)。
    • »提交 L' 从用户的角度来看(提交 = 快照)提交 L 的精确副本。« – 不,它不是同一个快照(除非快照 K和 E 已经相同),只是相同的差异(即 E→L' = K→L)。
    • @Paŭlo,您从上下文中提取了这句话,而不是只阅读下一个...:-) 此外,E→L' 和 K→L 的区别是不是 一样。
    • 是的,但是 K 的变化也适用,对吧?
    【解决方案6】:

    cherry-pick 是一个 Git 功能。如果有人想将一个分支中的特定提交提交到目标分支,则使用cherry-pick。
    git 樱桃采摘 步骤如下。

    1. 结帐(切换到)目标分支。
    2. git cherry-pick <commit id>
      

      这里的提交id是另一个分支的活动id。例如

      git cherry-pick 9772dd546a3609b06f84b680340fb84c5463264f
      
    3. 推送到目标分支

    访问https://git-scm.com/docs/git-cherry-pick

    【讨论】:

      【解决方案7】:

      您可以认为樱桃选择类似于变基,或者更确切地说,它像变基一样管理。我的意思是它接受一个现有的提交并重新生成它,以你当前所在分支的头部为起点。

      rebase 接受具有父 X 的提交并重新生成提交,就好像它实际上具有父 Y 一样,这正是 cherry-pick 所做的。

      Cherry pick 更多的是关于如何选择提交。使用pull (rebase),git 隐式地​​在你的分支上重新生成你的本地提交,但是使用cherry-pick 你显式地选择一些提交,并在你当前的分支上隐式地重新生成它(它们) .

      所以你做它的方式不同,但在底层它们是非常相似的操作——重新提交。

      【讨论】:

      • 我发现这是一个非常有用的观点。这暗示了为什么cherry-pick 的行为方式与稍后将目标分支合并回源分支时的行为方式相同。谢谢你,先生。
      • 我想在功能完成后使用cherry pick而不是git merge。每个人在完成一项功能时总是会执行 git merge feature_branch 。为什么不使用cherry-pick 命令?你有什么想法吗?如果我可以挑选,为什么还要费心压缩提交
      • 你可以将 rebase 看作是 reset 和 cherry-pick 的组合。
      • @j2emanue 相比于真正的合并,cherry-pick 会展平历史,如果你不注意的话,中间会出现非编译代码。与 squash 合并相比,它更难使用,因为您需要注意随身携带所有提交。
      【解决方案8】:

      它将对您当前的分支应用特定的提交。

      这意味着:

      • 此提交添加的所有文件都将被添加
      • 此提交删除的所有文件都将被删除
      • 此提交修改的所有文件都将被合并。这意味着来自提交的整个文件,而不仅仅是来自该提交的更改

      例如:考虑 commit A

      added newFileA
      modified main:
      + import './newFileA'
      

      提交 B

      added newFileB
      modified main:
      + import './newFileB'
      

      如果你在另一个分支上cherry-pick commit B,你最终会得到:

      /newFileB
      /main :
         import './newFileA'
         import './newFileB'
      

      由于commit B包含newFileBmain,但没有newFileA,导致出现bug,所以使用谨慎。

      【讨论】:

      • 当然是最有趣的答案,因为它讨论的是重要的文件,而不是整个提交。
      • 这个需要多加考虑,樱桃采摘的结果会导致危险的路径^^
      【解决方案9】:

      有点像复制(从某处)和粘贴(到某处),但针对特定的提交。

      例如,如果您想进行热修复,则可以使用cherry-pick 功能。

      在开发分支中执行您的cherry-pick,并在发布分支中提交merge。同样,从发布分支到 master 执行 cherry-pick。瞧

      【讨论】:

        【解决方案10】:

        当您与一组开发人员一起开发项目时,管理多个 git 分支之间的更改可能会成为一项复杂的任务。有时您不想将整个分支合并到另一个分支中,而只需要选择一个或两个特定的提交。这个过程被称为“樱桃采摘”。

        找到一篇关于樱桃采摘的精彩文章,查看详细信息:https://www.previousnext.com.au/blog/intro-cherry-picking-git

        【讨论】:

          【解决方案11】:

          如果你想在没有提交 ID 的情况下合并,你可以使用这个命令

          git cherry-pick master~2 master~0
          

          上面的命令会将master的最后三个commit从1合并到3

          如果您想为单个提交执行此操作,只需删除最后一个选项

          git cherry-pick master~2
          

          这样您将合并从 master 末尾的第三次提交。

          【讨论】:

          • 这令人困惑。我想你在这里不是master,对吧?当你提到两个提交时,你指的是 提交来定义你想要挑选的范围。正确的?如果描述了场景,将会有很大帮助。不过很好的补充。谢谢。
          【解决方案12】:

          摘自官方文档:

          给定一个或多个现有提交,分别应用更改 介绍,为每个记录一个新的提交。这需要您的 工作树要干净(不修改 HEAD 提交)。

          当不明确如何应用更改时,会发生以下情况:

          1. 当前分支和 HEAD 指针停留在最后一次提交 制作成功。

          2. CHERRY_PICK_HEAD 引用设置为指向引入的提交 难以应用的更改。

          3. 干净应用更改的路径在 index 文件和工作树中。

          4. 对于冲突的路径,索引文件最多记录三个版本,如 在 git-merge 的“TRUE MERGE”部分中描述。工作的 树文件将包含冲突的描述 常见的冲突标记 >>>>>。

          没有进行其他修改。

          Read more...

          【讨论】:

            猜你喜欢
            • 2016-06-12
            • 1970-01-01
            • 2017-02-05
            • 2021-01-18
            • 2019-07-17
            • 1970-01-01
            相关资源
            最近更新 更多