【问题标题】:How do cherry-pick and revert work?樱桃采摘和还原如何工作?
【发布时间】:2016-04-06 22:34:57
【问题描述】:

我试图了解合并和变基在数学中的集合操作方面的作用。

下文中,“-”表示diff(类似于数学中的取集差,但“AB”表示A中的但B中没有的,减去B中的而不A中的),“+”表示patch(即在数学中采用不相交的联合。我之前没有使用过patch,所以我不确定)。

来自使用 Git 的版本控制,作者 Loeliger,2ed

  1. 命令 git cherry-pick commit 应用由当前分支上的命名提交引入的更改。它将推出一个新的, 不同的提交。严格来说,使用 git cherry-pick 不会 更改存储库中的现有历史记录;相反,它增加了 历史。

    F' = (F-B) + Z 对吗?

  2. git revert commit 命令与命令 git cherry-pick commit 基本相似,但有一个重要区别: 它应用给定提交的倒数。因此,这个命令是 用于引入一个新的提交来反转给定的效果 提交。

    D' = G - D 对吗?

【问题讨论】:

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


【解决方案1】:

樱桃采摘

F' = (F-B) + Z 对吗?

不,这也会引入 CDE 中引入的更改。

git-cherry-pick 通过隔离提交中的唯一更改来进行挑选(即,在此示例中为 FE,忽略包括合并基础在内的其他祖先),并将它们应用于目标.

这不是通过补丁应用程序完成的,而是通过使用三向合并算法 - 要被挑选的提交的父级将用作共同祖先,要被挑选的提交将是一侧的合并,以目标为另一边。其结果是包含在精心挑选的提交和目标中的更改。

例如,如果 E 是要挑选的提交的父级,其内容(作为共同祖先)是:

Line 1
Line 2
Line 3
Line 4
Line 5

例如,如果 F 是要挑选的提交,其内容是:

Line 1
Line 2
Line Three
Line 4
Line 5

而樱桃挑选Z的目标是:

LINE 1
Line 2
Line 3
Line 4
Line 5!

那么三路合并的结果是(带有关于每行来自哪里的注释):

LINE 1
Line 2
Line Three
Line 4
Line 5!

还原

D' = G - D 对吗?

是的,粗略地说。 D 独有的更改已从 G 中删除。与git-cherry-pick 一样,git-revert 是使用三向合并实现的,虽然这次将要还原的提交视为共同祖先,一侧是当前提交,另一侧是要还原的父提交。

这意味着当要恢复的提交与当前提交之间的行相同时,将选择来自其父级的行。

如果是D的内容,则revert的提交是作为共同祖先,其内容是:

Line 1
Line 2
Line THREE
Line 4
Line FIVE

CD的父级)的内容是:

Line 1
Line 2
Line 3
Line 4
Line 5

G的内容又做了进一步的改动,其内容为:

Line One
Line 2
Line THREE
Line 4
Line FIVE

那么三路合并的结果会是:

Line One
Line 2
Line 3
Line 4
Line 5

这是在父 C 和目标 G 中取唯一行的结果。

合并提交

正如torek 所指出的(如下),由于这些机制都涉及使用父提交,因此当有多个父提交时,这些机制就会崩溃。 (即,有问题的提交是一个合并,并且有多个父级。)在这种情况下,您需要指定要考虑的 git 哪个 父级(使用-m 标志)。

冲突

当然,这两种机制中的任何一种都可能导致冲突。例如,如果当前的冲突进一步发生了变化,那么您将不得不解决冲突。例如,如果在 revert 示例(上面)中,后续提交也更改了第 5 行,那么 G 实际上是:

Line One
Line 2
Line THREE
Line 4
LINE FIVE!

那么就会有冲突。工作目录(合并文件)将是:

Line One
Line 2
Line 3
Line 4
<<<<<<<
LINE FIVE!
=======
Line 5
>>>>>>>

您需要决定是要原始更改 (Line 5) 还是最新更改 (LINE FIVE!)。

【讨论】:

  • 这里还值得一提的是,您不能挑选或恢复合并提交除非您告诉 git 使用多个父提​​交中的哪一个作为(假装单个)前驱节点。在@ 987654338或revering D时,您不需要这样做,因为它们已经只有​​一个前身节点。 span>
  • @torek 非常喜欢。我曾希望我能在雷达下隐藏这种区别。 :) 我更新了我的答案以试图澄清这一点。
  • 这是一个非常棒的答案!
  • 但是如果在提交 D 中添加第 6 行会怎样。由于提交 G 也会继承该行并且第 6 行不是在提交 C 中可以找到的相同行,这会被还原吗?如果在 Common Ancestor E 中添加了第 6 行,那么在挑选 Commit F 时也是如此。
【解决方案2】:

这样理解很简单:

cherry-pick

选择哪些提交(来自任何分支,甚至可以是松散提交)选择此提交并将其放置在我当前的分支中,换句话说 - 从存储库中的任何位置获取任何提交并将其添加到我的分支


revert

撤消任何提交。如果您知道补丁是什么,它将通过撤消它们来“恢复”提交中所做的任何更改,因此您可以将其视为在补丁-becommig + 中反转符号,反之亦然。您的更改正在“还原”并且正在撤消。

git revert 命令撤消已提交的快照。

但是,不是从项目历史记录中删除提交,
它弄清楚如何撤消提交引入的更改,并在结果内容中附加一个新的提交。

prevents Git from losing history,这对于您的修订历史的完整性和可靠的协作非常重要


F' = (F-B) + Z 对吗?

这只是意味着现在在较低的分支中,您还拥有在提交 F 中创建的补丁,您的较低分支包含其更改 + 在提交 F 中所做的更改(并且它们除了 F) 没有其他提交


D' = G - D 对吗?

不完全是 - 这意味着现在您有提交 D 并且在几次提交之后您可以撤消该提交,在存储库中您仍然有 2 个提交但代码将保持不变(更改 + 撤消 2 个单独的提交)

【讨论】:

  • 谢谢。我仍然不清楚 F' 和 D' 的组成以及它们是如何从现有提交中创建的。 (1) 在cherry-pick操作中,是F和Z的共同祖先,例如B、参与? (2)revert操作中,G如何参与?
  • 解决您的 2 Q: D' 是 D 的“撤消”,这意味着在 D 中完成的任何更改现在都在 D' 中撤消 - 您有 2 次提交。一个是原始的,第二个是撤消此提交。您的代码恢复到提交 D 之前的状态,但您有 2 次提交。 D=更改 D'=撤消更改。现在对你有意义吗?
  • revert操作中,G如何参与? G 没有进化,它是图 10-8 中的最后一次提交,D' 只是在它之后提交(图 10-9)
  • 谢谢。但还是没有。
  • 还有什么不明白的?
【解决方案3】:

Git 2.29(2020 年第四季度)解决了类似的情况

参见brian m. carlson (bk2204)commit 087c616commit 409f066commit 5065ce4(2020 年 9 月 20 日)。
(由 Junio C Hamano -- gitster -- 合并到 commit c5a8f1e,2020 年 9 月 29 日)

docs:解释为什么不总是在合并时应用还原

签字人:brian m.卡尔森

一个常见的场景是用户将更改应用到一个分支并将其挑选到另一个分支中,然后在第一个分支中恢复它。这导致两个分支合并时会出现变化,这让很多用户感到困惑。

我们已经在 git merge(man) 中提供了有关其工作原理的文档,但从被问到的频率可以清楚地看出,这很难掌握。
我们也不会向用户解释在这种情况下他们最好进行变基,这将达到他们的预期。
让我们在 FAQ 中添加一个条目,告诉用户发生了什么,并建议他们在此处使用 rebase。

gitfaq 现在包含在其man page 中:

如果我对两个分支进行了更改,但将其还原为一个,为什么这些分支的合并包含更改?

默认情况下,当 Git 进行合并时,它使用一种称为递归的策略 策略,它进行了花哨的三向合并。
在这种情况下,当 Git 执行合并,它只考虑三个点:两个头和一个 第三点,称为合并基础,通常是 那些提交。
Git 不考虑历史或单个提交 那些树枝上都发生过。

因此,如果双方都进行了更改并且一方已恢复该更改, 结果是包含更改
这是因为代码已更改 一方面,另一方面没有净变化,在这种情况下,Git 采纳更改。

如果这对你来说是个问题,你可以做一个变基,变基分支 恢复到另一个分支。
这种情况下的变基将恢复 更改,因为变基应用了每个单独的提交,包括 还原。
请注意,变基会重写历史记录,因此您应该避免变基 除非您确定自己对此感到满意,否则已发布分支。
有关详细信息,请参阅 git rebase 中的 NOTES 部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-07
    • 1970-01-01
    • 2020-02-11
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    相关资源
    最近更新 更多