我试图理解merge和rebase在数学中的集合操作方面做了什么.
在下文中," - "表示diff
(类似于数学中的设定差异,但"AB"表示A中的但不表示B中的表示,而B表示不表示A中的表示,而"+"表示patch
(即表示不相交联合)数学.我以前没用过patch
,所以我不确定).
来自Chacon的Pro Git,
最近共同祖先C2在这次合并中的作用是什么?
C5 =(C4-C2)+(C3-C2)+ C2是否正确?
对于rebase而不是merge:
C4'=(C4-C2)+ C3是正确的吗?
那么C5来自merge并且来自rebase的C4'具有相同的内容吗?
来自Loeliger的Git版本控制
W',X',Y'和Z'是如何产生的?
poke.. 6
你无法使用"diff"和"patch"语义正确地解释Git.原因是Git没有跟踪变化; 它跟踪内容.当你有一个提交A
与父母提交B
,那么对于Git的,A
是不是之间的差异B
和A
,即从需要得到改变B
到A
,但实际内容A
.您可以自己进行提交,并且您可以在此时重建存储库.
出于这个原因,我不会遵循你的"提交算术",而是试着用文字解释每个案例.
C5是两个父母C3和C4的合并提交,它们都有C2作为父母.因此,假设没有冲突,并且Git能够自己解析整个合并,那么C5将包含由以下两个等价表达式表示的内容:
C3应用了补丁,可以让你从C2到C4.
C4应用了补丁,可以让你从C2到C3.
所以在某种程度上,你可以用你的公式来表达它.
一个rebase基本上会让你处于完全相同的情况.唯一的区别是它实际上重写了它重新提交的提交,将它们的更改(补丁)重新应用到另一个提交.因此结果C4
将具有与C5
(1)相同的内容.
有了你的"算术",我一般会这么说(C3-C2) + C2 = C3
.所以这两个公式在这里也是等价的.
如上所述,rebase只是将提交补丁重新应用到另一个父级.Git正在编写包含与原始提交相同更改的新提交,但这些新提交将应用于不同的父提交.
因此,如果你想获得公式,它可能看起来像这样:
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之间的区别是什么?由于您不会以两种方式丢失提交(rebase将创建新的提交对象,但这些将保留所有原始信息),基本上所有关于更改历史记录的方式:
合并创建一个合并提交,允许清楚地看到历史分歧的位置(创建分支的位置)以及它再次联合的位置.这很好,因为你可以按照确切的发展.但它也会变得混乱,特别是如果你有多个并发分支线,最终会合并多次.
另一方面,重新定位使历史持平.它"伪造"它,所以一切都是线性发展,一切都接连不断.由于您总是在重新设置一个完整的分支,因此您可以将相关提交保持在一起,这样您仍然可以看到彼此相关的内容,但是您丢失了任何分支信息.此外,您正在创建新的提交对象,这将破坏已经知道这些提交对象的每个人的存储库(这就是为什么您不应该重新设置已发布的提交).
两种方式都有利有弊.它在很大程度上取决于存储库工作流程和个人偏好.
你无法使用"diff"和"patch"语义正确地解释Git.原因是Git没有跟踪变化; 它跟踪内容.当你有一个提交A
与父母提交B
,那么对于Git的,A
是不是之间的差异B
和A
,即从需要得到改变B
到A
,但实际内容A
.您可以自己进行提交,并且您可以在此时重建存储库.
出于这个原因,我不会遵循你的"提交算术",而是试着用文字解释每个案例.
C5是两个父母C3和C4的合并提交,它们都有C2作为父母.因此,假设没有冲突,并且Git能够自己解析整个合并,那么C5将包含由以下两个等价表达式表示的内容:
C3应用了补丁,可以让你从C2到C4.
C4应用了补丁,可以让你从C2到C3.
所以在某种程度上,你可以用你的公式来表达它.
一个rebase基本上会让你处于完全相同的情况.唯一的区别是它实际上重写了它重新提交的提交,将它们的更改(补丁)重新应用到另一个提交.因此结果C4
将具有与C5
(1)相同的内容.
有了你的"算术",我一般会这么说(C3-C2) + C2 = C3
.所以这两个公式在这里也是等价的.
如上所述,rebase只是将提交补丁重新应用到另一个父级.Git正在编写包含与原始提交相同更改的新提交,但这些新提交将应用于不同的父提交.
因此,如果你想获得公式,它可能看起来像这样:
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之间的区别是什么?由于您不会以两种方式丢失提交(rebase将创建新的提交对象,但这些将保留所有原始信息),基本上所有关于更改历史记录的方式:
合并创建一个合并提交,允许清楚地看到历史分歧的位置(创建分支的位置)以及它再次联合的位置.这很好,因为你可以按照确切的发展.但它也会变得混乱,特别是如果你有多个并发分支线,最终会合并多次.
另一方面,重新定位使历史持平.它"伪造"它,所以一切都是线性发展,一切都接连不断.由于您总是在重新设置一个完整的分支,因此您可以将相关提交保持在一起,这样您仍然可以看到彼此相关的内容,但是您丢失了任何分支信息.此外,您正在创建新的提交对象,这将破坏已经知道这些提交对象的每个人的存储库(这就是为什么您不应该重新设置已发布的提交).
两种方式都有利有弊.它在很大程度上取决于存储库工作流程和个人偏好.