为了理解Git为什么不提供你所谓的“继承机制”(不涉及提交),你必须首先理解这些SCMs(例如Git与ClearCase)的一个
核心概念。
在线性系统中,配置规范可以指定几个规则来实现您所看到的“继承”(对于给定文件,首先选择某个版本,如果不存在,则选择另一个版本,如果不存在,则选择第三个版本,依此类推)。
分支是给定选择规则下的线性历史中的分叉点(在该之前的所有其他选择规则仍然适用,因此产生了“继承”效果)。
在DAG中,一个提交代表了你将要获得的所有"继承";没有版本的"累积"选择。在此图中,只有一条路径可以选择你在这个确切点(提交)所看到的所有文件。
分支只是此图中的一条新路径。
在Git中应用其他版本,你必须执行以下操作之一:
但由于Git是基于DAG的SCM,它总会产生一个新的提交。
在Git中你失去的是某种"组合"(当你使用不同的连续选择规则选择不同的版本时),但这在一个
DVCS(如"Distributed")中是不可行的:当你用Git创建一个分支时,你需要以明确定义且易于复制到其他存储库的起始点和内容为基础。
在纯粹的中央VCS中,你可以使用任何你想要的规则来定义你的工作区(在ClearCase中,你的“视图”,快照或动态)。
unknown-google在评论中(以及上面的问题)补充道:
那么,一旦我们看到两个模型可以实现不同的事情(线性 vs DAG),我的问题是:在线性模型可以做到DAG不可能的事情的真实场景(特别是对于公司而言)是什么?它们是否值得?
当涉及到选择规则的“真实场景”时,在线性模型中您可以为
相同的文件集设置
多个选择规则。
考虑这个“配置规范”(即使用ClearCase进行选择规则的“配置规范”):
element /aPath/... aLabel3 -mkbranch myNewBranch
element /aPath/... aLabel2 -mkbranch myNewBranch
它选择所有标记为“
aLabel2
”的文件(并从那里开始分支),除了那些标记为“
aLabel3
”的文件-并从那里开始分支-(因为该规则优先于提到“
aLabel2
”的规则)。
值得吗?
不值得。
实际上,ClearCase的UCM Flavor(ClearCase产品中包含的“
统一配置管理”方法论,代表了从基本ClearCase使用中推导出的所有“最佳实践”)由于简化原因不允许这样做。一组文件称为“组件”,如果您想要针对给定标签(称为“基线”)进行分支,那么应按以下配置规范进行转换:
element /aPath/... .../myNewBranch
element /aPath/... aLabel3 -mkbranch myNewBranch
element /aPath/... /main/0 -mkbranch myNewBranch
你需要选择一个起点(这里是“
aLabel3
”)并从那里开始。如果你也想要“
aLabel2
”文件,你需要将所有“
aLabel2
”文件合并到“myNewBranch”中。
这是在DAG中不需要做的“简化”,其中图的每个节点都代表一个唯一定义的分支“起点”,无论涉及哪些文件集。
合并和变基足以将该起点与给定文件集的其他版本组合起来,以实现所需的“组合”,同时保持该特定历史记录在分支中的孤立状态。
总体目标是在“一致的组件”中应用“一致的版本控制操作”。
一个“一致”的文件集是处于一个明确定义的一致状态:
- 如果有标签,则所有文件都有标签。
- 如果分支,则所有文件都将从同一个唯一的起点分支出。
这在DAG系统中很容易实现;在线性系统中可能更难(特别是在“Base ClearCase”中,“配置说明”可能会很棘手),但在UCM方法论中,这种基于线性工具的方法是强制执行的。
与使用私有选择规则技巧(例如ClearCase的某些选择规则顺序)实现“组合”不同,您只需使用VCS操作(rebase或merge)即可实现它,这些操作留下了明显的痕迹供所有人跟踪(而不是开发人员专用或仅在一些而非所有开发人员之间共享的配置规范)。再次强调它强制实施了
连贯性,与“动态灵活性”相对应,后者可能难以在以后复制。
这使您可以离开
VCS(版本控制系统)领域,进入主要关注“
可重复性”的
SCM(软件配置管理)领域。并且这些(SCM特性)可以通过基于线性或基于DAG的VCS实现。