每个开发者都应该知道的 Clearcase 版本控制系统的核心概念是什么?
7 回答
核心概念?
集中式(复制)VCS:ClearCase 介于集中式 VCS 世界(一个或多个“集中式”存储库或 VOBS - 版本对象库 - 每个开发人员必须访问才能提交)和分布式 VCS 世界之间。
但它也支持“复制”模式,允许您在远程站点 (MultiSite ClearCase) 中复制存储库、发送增量和管理所有权。(尽管随之而来的许可费用相当高)
这不是一个真正的“去中心化”模型,因为它不允许并行并发进化:分支掌握在一个 VOB 或另一个;您只能为在那里掌握的分支签入主 VOB,尽管您对任何副本的任何分支具有只读访问权限。线性版本存储:每个文件和目录都有一个线性历史;它们之间没有直接关系,例如 DAG VCS(有向无环图),其中文件的历史记录链接到链接到提交的目录之一。
这意味着- 当您比较两个提交时,您必须比较所有文件和目录的列表以找到增量,因为提交不是跨文件或目录的原子,这意味着对构成一个的所有文件的所有更改没有单一名称逻辑增量。
这也意味着合并必须通过历史探索(见下一点)找到一个共同的基础贡献者(并不总是与共同的祖先相同)。
(Git 处于该频谱的另一端,既分散又面向 DAG:
- 如果其图的节点与不同提交的节点具有相同的“id”,则不必进一步探索:所有子图都保证相同
- 两个分支的合并实际上是一个 DAG 中两个节点的内容的合并:递归并且非常快速地找到一个共同的祖先)
三向合并:要合并两个版本,ClearCase 必须在它们的线性历史中找到一个基于公共的贡献者,这对于复杂的版本树(分支/子分支/子子/分支,...)可能相当长,并且基本的ClearCase 合并命令合并一个文件或目录,但它不是递归的。它只影响单个文件或没有文件的单个目录(
ct findmerge
是递归的)以文件为中心(与其他最近的以存储库为中心的 VCS 相反):这意味着提交是逐个文件的,而不是“修改文件集”:事务是在文件级别的。多个文件的提交不是原子的。
(几乎所有其他现代工具都是“以存储库为中心”,具有原子提交事务,但第一代系统,如 RCS、SCCS、CVS 和大多数其他较旧的系统都没有该功能。)id-managed:每个文件和目录都有一个唯一的 id,这意味着它们可以随意重命名:它们的历史不会改变,因为 id 仍然是“元素”。另外,目录将在其历史记录中检测到文件的任何添加/抑制。
rmname
当一个文件被“移除”(
(创建两个大小和内容相同的文件,它们将在 Git 中获得相同的 id——一个 SHA1 密钥——并且只会在 Git 存储库中存储一次!在 ClearCase 中不是这样。
另外,如果两个文件具有相同的path 和 name 在两个不同的分支中创建,它们的 id 不同意味着这两个文件永远不会被合并:它们被称为“邪恶双胞胎”)
分支是一等公民:大多数 VCS 将分支和标签视为相同:历史中的一个点,新的线性历史可以从该点开始(分支)或附加描述(标签)。
对于 ClearCase 来说并非如此,其中分支是引用版本号的一种方式。任何版本号都从 0(仅在 ClearCase 中引用)到 1、2、3 等开始。每个分支都可以包含一个新的版本号列表(又是 0、1、2、3)。
这不同于其他版本号是唯一的并且一直在增长的系统(如 SVN 中的修订版),或者只是唯一的(如 Git 中的 SHA1 键)。path-accessed:要访问某个版本的文件/目录,您需要知道其扩展路径(由分支和版本组成)。它被称为“扩展路径名”:
myFile@@/main/subBranch/Version
.
(Git 确实通过 id 引用所有内容——基于 SHA1——:版本 [或提交]、树 [或目录的版本] 和 blob [或文件的版本,或者更确切地说是文件的内容]。所以它是“id-accessed”或“id-referenced”。
对于 ClearCase,id 指的是“元素”:目录或文件,无论其版本是什么。)
悲观锁和乐观锁:(ClearCase 中的保留或非保留签出):即使是悲观锁(保留签出)也不是真正的悲观锁,因为其他用户仍然可以签出该文件(尽管处于“非保留模式”):他们可以更改它,但必须等待第一个用户提交他的文件(签入)或取消请求。然后他们将合并同一文件的结帐版本。
(注意:“保留”结帐可以由所有者或管理员释放其锁定并变为未保留)便宜的分支:一个分支不会触发所有文件的副本。它实际上什么也没触发:任何未检出的文件都将保留在其原始分支中。只有修改过的文件才会将其新版本存储在声明的分支中。
平面文件存储:VOB 以简单文件的专有格式存储。这不是一个具有简单查询语言的数据库。
本地或网络工作区访问:
- 本地工作区是通过结帐到硬盘驱动器(快照视图的“更新”)。
- 网络工作空间是通过动态视图,通过网络(无本地副本,即时访问)和本地文件(签出的文件或私有文件)结合版本化文件和目录访问。远程(版本化)和本地(私有)文件的组合允许动态视图看起来像经典硬盘驱动器(而实际上任何“写入”的文件都存储在关联的视图存储中)。
集中驱逐存储:[视图]存储用于保存一些数据并避免与中央引用进行一些或任何通信。
工作区可以有:- 分散的存储:就像
.svn
到处都是子目录 - 集中式存储:类似于 ClearCase 中的视图存储,它们包含有关视图显示的文件的信息,并且该存储对于视图来说是唯一的。
- 被驱逐的存储:存储不是视图/工作区本身的一部分,但可以位于计算机上的其他位置,甚至可以位于 LAN/WAN 外部
- 分散的存储:就像
(Git 本身没有“存储”。它.git
实际上是所有的存储库!)
- 面向元数据:任何“键值”都可以附加到文件或目录,但是这对数据本身不会被历史化:如果值发生变化,它会覆盖旧值。
(这意味着该机制实际上比 SVN 的“属性”系统弱,其中属性可以有历史;
另一端的 Git 不太热衷于元数据)
- 基于系统的保护:与文件/目录或存储库关联的所有者和权限基于底层系统的权限管理。ClearCase 中没有应用账户,用户组直接基于 Windows 或 Unix 现有组(这在异构环境中相当具有挑战性,有 Windows 客户端和 Unix VOB 服务器!)
(SVN更像是“基于服务器”的保护,Apache服务器可以得到第一级的保护,但必须用钩子完成才能拥有更细粒度的权限
。Git没有直接的权限管理,必须通过钩子来控制在存储库之间推送或拉取期间)
可用的钩子:任何 ClearCase 操作都可以成为钩子的目标,称为触发器。它可以是前操作或后操作。
CLI 管理:cleartool 是命令行界面,可以从中执行所有操作。
ClearCase 是一个好用的野兽。慢,有车,而且很贵。我为应对使用 CC 所做的一些事情是:
- 入住时请务必发表好评。
- 使用通用配置规范,不要经常更改。
- 切勿尝试通过 VPN 或慢速网络连接使用 CC。
- 启动时关闭加载关闭CC医生。
- 不要将文件移动到不同的目录。
- 为每个文件安排至少 2 分钟的签入时间。
- 快照视图很慢,但动态视图更慢。
- 养成尽早并经常签入的开发习惯,因为保留文件和合并很痛苦。
- 默认情况下,让所有开发人员签出未保留的文件。
我们使用 CC 已经超过十五年了。它有很多很好的功能。
我们所有的开发都是在分支上完成的;我今天创建了一对,用于几组不同的更改。当我检查到分支时,我让一位同事审查更改,然后合并回 /main/LATEST - 这恰好是我需要去的地方。如果它是针对分支上的较旧版本,那将不会更难。
我的临时分支的合并是全自动的;在我签出文件时,没有人更改过我处理的文件。尽管默认情况下结帐是保留(锁定)的,但您始终可以稍后取消保留结帐,或创建未保留的结帐。当更改需要几天时间时,我的临时分支与主分支的重新同步很容易并且通常是自动的。合并工具没问题;对我来说最大的问题是我的服务器机器离我的办公室(或家)大约 1800 英里,所以那个距离上的 X 有点慢(但不是不能忍受的)。我没有使用过更好的合并工具,但这可能没什么意义,因为我没有使用任何其他图形合并工具。
视图(动态视图)在我们的设置中很快。我没有使用过快照视图,但是当我可以提供帮助时,我不会在 Windows 上工作(我们的团队在 Windows 上使用快照视图;我不清楚为什么)。我们有复杂的分支系统,但是主要的开发是在 /main/LATEST 上完成的,而发布工作是在一个分支上完成的。在 GA 之后,维护工作在特定于发布的分支上完成,并向前合并到 /main/LATEST(通过任何中间版本)。
CC 确实需要优秀的管理员——我们有他们并且很幸运能够这样做。
CC 的使用并非微不足道,尽管目前,我发现 'git' 就像 CC 对那些没有使用过它的人一样令人生畏。但基本原理是相同的——结账、更改、签入、合并、分支等等。目录可以分支 - 谨慎 - 当然是版本控制的。那是无价的。
我没有看到办公室从 CC 切换。
嵌入式版本号 - 好还是坏?
我写:
我对 CC 的最大问题是它没有将版本号嵌入到源文件中——git 也有这个问题,AFAICT。我能明白为什么;不过,我不确定我是否喜欢放弃这种可追踪性。所以,在我的大部分个人工作中,我仍然使用 RCS(甚至不是 CVS)。有一天,我可能会切换到 git - 但这将是一个颠簸,并且需要大量工作来重新配置围绕(SCCS 和)RCS 配置的发布系统。
作为回应,@VonC 指出:
我们一直认为这种做法是邪恶的(将元数据信息混合到数据中),引入了“合并地狱”。另请参阅如何在 Java 文件中获取 Clearcase 文件版本。当然,您可以使用触发器进行 RCS 关键字替换(Clearcase 手册:检查触发器示例),前提是您使用了适当的合并管理器。
这次讨论暴露了几个问题,它们都混在一起了。我的观点近乎过时,但背后有一个基本原理,我会花时间把它们写下来(被生活搞砸了——可能需要多次编辑才能完成)。
背景
我在 1984 年学习 SCCS,大约在 RCS 发布的时间(我相信是 1983 年),但 SCCS 在我的机器上,互联网充其量只是新生。我在 90 年代中期不情愿地从 SCCS 转到 RCS,因为 SCCS 日期格式多年来一直使用两位数,而且尚不清楚 SCCS 是否会在时间上普遍固定(确实如此)。在某些方面,我不像 SCCS 那样喜欢 RCS,但它有一些优点。在商业上,我的雇主使用 SCCS 直到 1995 年年中,但他们从 1994 年初开始切换到 Atria ClearCase,一次处理一个单独的产品集。
早期的 ClearCase 实验与触发器 - 并合并地狱
我们的项目后来迁移了,当时已经有了一些 CC 经验。部分因为我坚持,我们通过签入触发器将版本控制信息嵌入到源文件中。这持续了一段时间——但只是一段时间——因为正如 VonC 所说,它会导致合并地狱。问题是,如果带有标签 /main/branch1/N 的版本与来自公共基本版本 /main/B 的 /main/M 合并,则文件的提取版本包含一行,每个版本都有编辑 -冲突。而且这种冲突必须手动解决,而不是自动处理。
现在,SCCS 有了 ID 关键字。ID 关键字有两种格式,一种用于正在编辑的文件,另一种用于未编辑的文件:
Edit Non-Edit
%I% 9.13
%E% 06/03/09
%Z% @(#)
%M% s.stderr.c
如果您尝试对 SCCS 文件的可编辑版本进行 3 路合并(使用 %x% 表示法),则包含元数据的行不会发生冲突,除非您更改了这些行上的元数据(例如,通过从 US-样式 %D% 日期到英国样式 %E% 日期 - SCCS 不支持 ISO 样式 2009-03-15 日期作为标准。)
RCS 也有关键字机制,关键字也有两种格式,一种是针对尚未插入 RCS 的文件,另一种是针对具有以下内容的文件:
Original After insertion
$Revision$ $Revision: 9.13 $
$Date$ $Date: 2009/03/06 06:52:26 $
$RCSfile$ $RCSfile: stderr.c,v $
区别在于关键字后面的“$”和“:”、空格、文本、空格,最后是“$”。我没有对 RCS 进行足够的合并来确定它对关键字信息的作用,但我注意到如果它将扩展和“收缩”符号视为等效(不管扩展材料的内容如何),那么合并可以在没有冲突的情况下发生,在合并的输出中留下约定的符号,当签入后检索结果文件时,它将被适当地扩展。
ClearCase 问题是缺少合适的合并管理器
正如我在对 SCCS 和 RCS 的讨论中指出的那样,如果完成 3 路合并,以正确(收缩或可编辑)格式处理关键字,则不存在合并冲突。
CC 的问题(从这个角度来看——显然,CC 的实现者不同意)是它缺乏处理关键字的系统,因此也缺乏适当的合并管理器。
如果有处理关键字的系统和适当的合并管理器,那么:
- 系统会自动将元数据嵌入到适当标记的文件中。
- 在合并时,系统会识别出带有元数据标记的行不会发生冲突,除非标记发生不同的变化——它会忽略元数据内容。
这样做的缺点是它需要一个特殊的差异工具来识别元数据标记并对其进行特殊处理,或者它需要将提供给差异工具的文件进行规范化(元数据标记被简化为中性形式 - $Keyword$ 或RCS 和 SCCS 术语中的 %K%)。我确信这一点额外的工作是它不被支持的原因,我一直觉得在如此强大的系统中是短视的。我对 RCS 或 SCCS 表示法没有特别的依恋——SCCS 表示法在某些方面更容易处理,但它们本质上是等价的——并且可以使用任何等价的表示法。
为什么我仍然认为文件中的元数据很好
我喜欢在源代码中包含元数据,因为我的源代码(而不是我雇主的源代码)分布在源代码控制系统的保护之外。也就是说,它主要是开源的——我让所有人都可以使用它。如果有人报告文件中的问题,特别是在他们修改过的文件中,我认为知道他们从哪里开始会很有帮助,这由源文件中的原始元数据表示。
在这里,SCCS 比 RCS 有一个优势:SCCS 关键字的扩展形式与常规文本没有区别,而 RCS 关键字仍然看起来像关键字,因此如果其他人已将材料导入自己的 RCS 存储库,则他们的元数据会替换我的元数据,SCCS 不会以同样的方式发生问题(其他人必须工作才能覆盖元数据)。
因此,即使有人拿走了我的一大块源代码并对其进行了修改,其中通常有足够的标签来识别它的来源,而不是让我推测它基于哪个版本。反过来,这也让我们更容易看出问题的哪些部分是我造成的,以及问题的哪些部分是他们造成的。
现在,在实践中,开源的工作方式,人们并不像你想象的那样迁移代码。他们倾向于相当紧密地坚持发布的版本,仅仅是因为在下一次正式发布时偏离太昂贵了。
我不确定您应该如何确定源自您的工作并从那时起经过修订的一段源代码的基本版本。不过,找到正确的版本似乎是做到这一点的关键,如果代码中有指纹,那就更容易了。
所以,这就是我为什么喜欢在源文件中嵌入版本信息的一个适度的总结。这在很大程度上是历史性的——SCCS 和 RCS 都这样做了,我喜欢他们这样做的事实。它可能是古老的遗物,是 DVCS 时代要告别的东西。但我还没有完全相信这一点。但是,可能需要更多的文章来解释我的发布管理机制的来龙去脉,才能了解我为什么要这样做。
推理的一个方面是关键文件,例如“stderr.c”和“stderr.h”,基本上被我的所有程序使用。当我发布一个使用它的程序时,我只是确保我拥有最新的版本——除非有一个需要回溯版本的接口更改。我已经有一段时间没有遇到这个问题了(我在 2003 年进行了系统重命名;这引起了一些过渡性的头痛,但是 Perl 脚本让我可以很容易地实现重命名)。我不知道有多少程序使用该代码 - 100 到 200 之间的某个地方是一个合理的猜测。今年的一系列变化(9.x 系列)仍然有些投机性;我还没有最终决定是否保留它们。它们也是实现的内部,不影响外部接口,所以我不 我现在还不需要下定决心。我不确定如何使用 git 来处理它。我不想将库代码构建成必须在构建我的软件之前安装的库——这对我的客户来说太繁重了。因此,每个程序将继续分发库代码的副本(另一种繁重的),但只有程序需要的库代码,而不是整个库。我为每个程序挑选并选择使用哪些库函数。所以,我不会导出整个子树;实际上,涵盖库代码中最后更改的提交通常与涵盖程序中最后更改的提交完全无关。我什至不确定 git 是否应该为库使用一个存储库,为使用它的程序使用另一个存储库,还是应该使用一个更大的通用存储库。
好的-足够的wittering。我所拥有的对我有用;不一定适合所有人。它对 VCS 没有特别的要求——但它确实需要文件中嵌入的版本元数据,而 CC、Git 和(我认为)SVN 对此有问题。这可能意味着我是一个有问题的人——为失去的过去挂断电话。但我重视过去所提供的东西。(我可以侥幸逃脱,因为我的大部分代码都没有分支。我不确定分支会产生多大的不同。)
我与 clearcase 一起工作了 6 年的大部分时间,并且普遍认为它是可以忍受的。它确实有一定的学习曲线,但是一旦你习惯了这些怪癖,你就可以顺利地使用它。一个非常称职的 CC 管理员知道自己在做什么,这对于除琐碎设置之外的任何事情都是必不可少的。除非你有一个,否则人们会遇到问题,很快就会有关于“ClearCase”问题的讨论。然后管理层将不得不通过切换到其他方式进行干预,这只会浪费所有相关人员的时间。CC 不是一个糟糕的产品,只是有时人们对它了解甚少。
以下是我认为重要的几个概念,其中一些并非完全面向 CC -
- 结帐不同于常规的类似 CVS 的结帐概念。签出时会锁定文件,直到签入。
- 移动文件没有问题。事实上,这完美无缺。
- 版本树对于理解文件发生的事情至关重要。对于活动文件,它们可能会变得非常混乱,但是当您习惯观看它们时,它会成为一种非常有用的工具,并且是其他源代码控制工具(例如 SVN)中非常缺乏的工具(在某种程度上)。
- 在任何情况下都不要使用动态视图。这不值得。
- 在创建新的分支、流或项目之前,请咨询您的管理员,以确保您创建的内容真正能为您提供最佳服务。开始新的代码库时,请确保通过提前计划从一开始就获得流和项目布局。如果可能的话,以后更改它是一个真正的头痛。
- 微调用户权限并为常见事件设置触发器,以防止常见错误或强制执行策略。服务器是非常可配置的,对于您遇到的大多数问题,可能有一个合理的解决方案。
- 对开发人员进行从基本概念到高级操作的任何方面的教育。可以使用 cleartool 找到问题所在的高级用户可以降低管理员的负担。
- 不要留下悬空的流和视图。当开发人员离开项目时,有人可以删除他在他的机器上拥有的所有视图并删除他所有的私有流。不保持服务器清洁会导致...它变脏并且随着时间的推移变慢。当您对所有流和视图执行“查找所有签出”时,您不应该看到由不再存在的人签出的文件。
- 为子分支强制执行“始终在交付前变基”策略,以避免人们在交付与最近更改冲突的代码时“破坏集成流”。
- 持续集成- 当每个开发人员或团队在自己的分支上工作时,不要让集成流停滞。如果不交付稳定的更改,则每 X 次每个人都必须至少重新定位到最新的集成基线时强制执行一次。这确实很难做到,特别是对于大型项目,但另一种选择是“集成地狱”,在月底没有人做任何事情 3 天,而一些可怜的草皮试图让所有的变化结合在一起
如何在 ClearCase 之上使用 git!
- Git 后台,在幕后和低处
- Git 的 Clearcase , git-cc 桥
我使用 Clearcase 和 SVN 成功地完成了许多大中型项目。两者都是很棒的工具,但使用它们的团队需要记录在案的流程。创建一个描述您将如何使用版本控制系统的过程。
1) 为您的版本控制系统查找或创建最佳实践文档。这是subversion的一个,将其调整为您的 Clearcase 流程。所有开发者都必须遵守相同的游戏计划。
基本上决定你是要“总是分支”还是“从不分支”。
从不分支方案:
- 从不分支方案是 SourceSafe 在签出期间锁定文件并在签入期间可用的地方使用的方案。此方案适用于小型(1 或 2 个开发人员)团队项目。
始终分支方案:
- 始终分支方案意味着开发人员为每个错误修复或功能添加创建分支。大型项目需要此方案,该项目有负责人(buildmeister)管理 Clearcase 中的 /main/LATEST 或 SVN 中的 /trunk 允许哪些更改。
- 始终分支方案意味着您可以经常签入而不必担心破坏构建。只有在您的错误修复或功能完成并将其合并到 /main/LATEST 之后,您才能打破构建的唯一机会。
“需要时分支”是一种折衷方案,可能最适合许多项目。
2) 使用 Clearcase(和 Subversion)你必须学会合并——合并是你的朋友。学习使用 Clearcase 的合并功能或使用Beyond Compare或 emacs-diff 之类的工具。如果您的项目模块化良好(许多小的解耦文件),您将受益于合并期间更少(或没有)冲突。
3)享受。
如果您使用的是 ClearCase,请确保您使用它附带的 UCM 和复合组件。
它使您的所有分支/合并都毫不费力。我说的是运行 6 个月的主要重组分支,涉及数万次更改,包括目录重命名、文件重命名等,它们会自动解决 99.9% 的增量。
此外,我们只使用 SnapShot 视图,而不是动态视图。我们的快照视图加载速度比您从网络驱动器拖放 (Windows) 相同的源树要快。
我对 UCM 的唯一抱怨是历史不能跨越组件。如果将一个组件拆分为多个新组件,则每个新组件都从 /main/0 开始。