如何挑选和恢复工作?

时间:2016-01-03 00:15:51

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

我试图理解merge和rebase在数学中的set操作方面做了什么。

在下文中," - "意味着diff(类似于数学中的设定差异,但是" A-B"意味着A中但不是B中的那些而减去B中而不是A中的那些)和" + "意味着patch(即在数学中采用不相交的联合。我之前没有使用patch,所以我不确定。)

使用Git进行版本控制,来自Loeliger,2ed

  1.   

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

    enter image description here

    enter image description here

    F'是否正确? =(F-B)+ Z?

  2.   

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

    enter image description here

    enter image description here

    D'是否正确? = G - D?

3 个答案:

答案 0 :(得分:6)

樱桃挑选

  

F'=(F-B)+ Z?

是否正确

不,这也会引入 C D E 中引入的更改。

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?

是否正确

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

这意味着当提交还原和当前提交之间的行相同时,将选择来自其父级的行。

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

Line 1
Line 2
Line THREE
Line 4
Line FIVE

C D 的父级)的内容是:

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标志)。 / p>

冲突

当然,这些机制中的任何一种都可能导致冲突。例如,如果当前冲突进一步已更改,则您必须解决冲突。例如,如果在恢复示例(上面)中,后续提交也更改了第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!)。

答案 1 :(得分: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个单独的提交中更改+撤消)

答案 2 :(得分:1)

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

请参见commit 087c616commit 409f066commit 5065ce4brian m. carlson (bk2204)(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 rebaseNOTES部分。

相关问题