【发布时间】:2016-01-02 23:54:38
【问题描述】:
我试图了解合并和变基的作用,就数学中的集合操作而言。
下文中,“-”表示diff(类似于数学中取集差,但“A-B”表示A中不存在B,减去B不属于A),“+”表示patch(即在数学中采用不相交的联合。我之前没有使用过patch,所以我不确定)。
【问题讨论】:
-
谢谢。检查对我的符号解释的编辑。
标签: git git-merge git-rebase
我试图了解合并和变基的作用,就数学中的集合操作而言。
下文中,“-”表示diff(类似于数学中取集差,但“A-B”表示A中不存在B,减去B不属于A),“+”表示patch(即在数学中采用不相交的联合。我之前没有使用过patch,所以我不确定)。
【问题讨论】:
标签: git git-merge git-rebase
您无法使用“差异”和“补丁”语义真正正确地解释 Git。原因是 Git 不跟踪更改。它跟踪内容。当您有一个提交A 和一个父提交B 时,对于Git,A 不是B 和A 之间的区别,即从B 到@987654328 所需的更改@,而是A的实际内容。您可以自行提交,此时您拥有重建存储库的一切。
因此,我不会遵循您的“提交算术”,而是尝试用文字解释每种情况。
C5 是与两个父级 C3 和 C4 的合并提交,它们都将 C2 作为父级。所以假设没有冲突,并且Git能够自己解决整个合并,那么C5将包含以下两个等价表达式表达的内容:
所以在某种程度上,你可以用你的公式来制定它。
变基基本上会让你处于完全相同的境地。唯一的区别是它实际上重写了它变基的提交,将它们的更改(补丁)重新应用到另一个提交。所以结果 C4 将与 (1) 中的 C5 具有相同的内容。
对于你的“算术”,我通常会说(C3-C2) + C2 = C3。所以这两个公式在这里也是等价的。
如上所述,rebase 只是将提交补丁重新应用到另一个父级。 Git 正在编写包含与原始提交相同的 change 的新提交,但这些新提交将应用于不同的父级。
因此,如果您想为此获取公式,它可能看起来像这样:
W' = E + (W - B) (the patch from B to W, applied on E)
X' = W' + (X - W) (the patch from W to X, applied on W')
Y' = X' + (Y - X) (the patch from X to Y, applied on X')
Z' = Y' + (Z - Y) (the patch from Y to Z, applied on Y')
因此W 的基础更改为E 而不是B,并且所有后续提交都只是更新为跟进新的提交W'。
但同样,Z' 的结果与合并E 和Z 的合并提交具有相同的内容。
这一切都给我们留下了一个问题:如果合并和变基都产生相同的内容,那么它们之间有什么区别?由于您不会以两种方式丢失提交(rebase 将创建新的提交对象,但这些对象将保留所有原始信息),所以基本上都是为了改变历史的样子:
合并创建一个合并提交,可以清楚地查看历史分歧的位置(创建分支的位置)以及再次合并的位置。这很好,因为您可以遵循确切的发展。但它也可能变得混乱,特别是如果您有多个并发分支线最终合并多次。
另一方面,重新定基会使历史变平。它“伪造”了它,所以一切都是线性发展,一切都顺理成章地接踵而至。由于您总是重新定位一个完整的分支,因此您将相关的提交保存在一起,因此您仍然可以看到彼此属于什么,但您会丢失任何分支信息。此外,您正在创建新的提交对象,这将破坏已经知道这些提交对象的每个人的存储库(这就是为什么您永远不应该对已发布的提交进行变基)。
这两种方式各有利弊。这在很大程度上取决于存储库工作流程和个人偏好。
【讨论】:
--interactive,是)内部的一系列git cherry-pick操作。
git-cherry-pick 操作,如果您使用 git rebase --merge 或 git rebase --interactive 调用它。不过,默认情况下,rebase 会创建一系列补丁,然后应用它们。
最近的共同祖先 C2 在这次合并中的作用是什么?
C5 = (C4-C2) + (C3-C2) + C2 对吗?
最近的共同祖先用于确定在master 中尚未出现的分支experiment(在您的示例中)中进行了哪些更改(参数是所有提交可以从experiment 分支的分支尖端在最后一个共同祖先还不是主分支的一部分。
当将experiment 分支合并到master 和git merge experiment 时,Git 然后使用共同祖先和要合并分支的分支尖端(在本例中为experiment)之间的增量来计算在合并提交中应用哪些更改。
在您为问题选择的集合符号中,我将其表示为 C5 = C3 + (C4 - C2)。
C4' = (C4-C2) + C3 对吗?
那么,merge 中的 C5 和 rebase 中的 C4' 内容相同吗?
这两个假设都是正确的。请记住,git rebase 保持提交的增量不变,因此在您的示例中,表达式 (C4' - C3) = (C4 - C2) 为真。
W'、X'、Y'、Z'是如何生成的?
如前所述,git rebase 保留了提交的增量。这意味着(例如)W 与其父提交 B(或 W - B,您也可以使用 @ 生成)之间的差异987654330@)。
然后,rebase 只需将相同的增量应用于新的父提交;所以在你的例子中 (W' - E) = (W - B) (相应地对于 X、Y 和 Z)。
【讨论】:
最近的共同祖先 C2 在这次合并中的作用是什么?
c2c3+c4 有 2 个父母
变基而不是合并的全部意义在于,您将有一条“直线”,而不是途中的所有那些叉子(蛇形)。
您将工作放在分支的顶部,作为信号线,在合并中,您将至少有 2 个父级(提交)到合并点。
【讨论】: