我试图理解merge和rebase在数学中的set操作方面做了什么。
在下文中," - "意味着diff
(类似于数学中的设定差异,但是" A-B"意味着A中但不是B中的那些而减去B中而不是A中的那些)和" + "意味着patch
(即在数学中采用不相交的联合。我之前没有使用patch
,所以我不确定。)
使用Git进行版本控制,来自Loeliger,2ed
答案 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 087c616的commit 409f066,commit 5065ce4,brian 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 rebase
的NOTES
部分。