当前位置: 首页 > 科技观察

ThePre-GitEra-VersionControlwithCVS

时间:2023-03-12 01:00:19 科技观察

GitHub网站于2008年上线。如果你的软件工程师生涯比我晚,Git可能是你用过的唯一版本控制软件。尽管它陡峭的学习曲线和不直观的用户界面经常被人抱怨,但不可否认的是,Git已经成为每个人学习版本控制的选择。根据StackOverflow2015年的开发者调查,69.3%的受访者使用Git,几乎是排名第二的版本控制系统Subversion用户数量的两倍。12015年之后,也许是因为Git变得如此流行以至于人们对这个话题失去了兴趣,StackOverflow停止了关于开发人员使用的版本控制系统的投票。GitHub的发布时间与Git本身的发布时间非常接近。2005年,LinusTorvalds发布了Git的第一个版本。今天年轻一代的开发者可能很难想象“版本控制软件”这个词所代表的世界不仅仅是Git,尽管这样的世界已经很久没有诞生了。Git有很多替代品。那时,开源开发人员首选Subversion,企业和视频游戏公司使用Perforce(有些公司至今仍在使用),Linux内核项目依赖于名为BitKeeper的版本控制系统。其中一些系统,特别是BitKeeper,对于年长的Git用户来说会感觉熟悉并且可以快速上手,但大多数系统差异很大。除了BitKeeper之外,Git之前的版本控制系统都运行在不同的架构模型上。《Version Control By Example》的作者EricSink在他的书中对版本控制进行了分类。据他介绍,Git属于第三代版本控制系统,Git的前身,流行于1990年代和21世纪初的系统,大部分都属于第二代版本控制系统。2第三代版本控制系统是分布式的,第二代是集中式的。您之前可能听说过Git被描述为“分布式”版本控制系统。一直搞不懂分布式/集中式的区别,后来自己安装了一个二代集中式版本控制系统,并做了相关实验,至少了解了一些。我安装的版本系统是CVS。CVS,“ConcurrentVersionsSystem”的缩写,原为第二代版本控制系统。在2000年被Subversion取代之前,它是大约十年来最流行的版本控制系统。即便如此,Subversion仍被认为是“更好的CVS”,这进一步加强了CVS在1990年代的统治地位。CVS最初于1986年由一位名叫DickGrune的荷兰科学家开发,当时他有一个编译器项目,正在寻找一种与他的学生合作的方法。3CVS最初只是一个包裹了RCS(RevisionControlSystem)的shell脚本集合,Grune想要改进这个第一代版本控制系统。RCS工作在悲观锁模式下,这意味着两个程序员不能同时在同一个文件上工作。如果需要编辑文件,首先要向RCS系统申请独占锁,锁定文件直到编辑完成。如果你要编辑的文件正在被别人编辑,你必须等待。CVS在RCS的基础上进行了改进,用乐观锁模型取代了悲观锁模型,迎来了第二代版本控制系统时代。程序员现在可以同时编辑同一个文件,合并编辑,然后解决合并冲突。(BrianBerliner,后来接手CVS项目的工程师,在1990年写了一篇非常可读的关于CVS创新的论文。)从这个意义上说,CVS和Git没有什么不同,因为Git也运行在乐观锁定模式下,但这是唯一的相似。事实上,当LinusTorvalds开发Git时,他的指导原则之一就是WWCVSND,意思是“WhatWouldCVSNotDoCVSCannotDo”。每当他做出决定时,他都会努力选择CVS设计中未使用的功能选项。4所以即使CVS比Git早十多年,它对Git的影响是负面的。我真的很喜欢摆弄CVS。我认为没有比折腾CVS更好的方式来理解为什么Git的分布式特性比以前的版本控制系统有了很大的改进。因此,我邀请您与我一起踏上激动人心的旅程,并在接下来的十分钟内学习这款拥有近十年历史的软件。(可以看文末“纠错”部分)CVS入门CVS的安装教程可以在它的项目主页上找到。对于MacOS系统,可以使用Homebrew安装。由于CVS是中心化的,它有客户端和服务器的区别,而Git没有。每一端都有不同的可执行文件,区别不太明显。但是要开始使用CVS,即使只是在您的本地机器上,您也必须设置CVS服务器后端。CVS的后端,所有代码的中央存储库,称为存储库。在Git中,每个项目都有一个存储库,而在CVS中,一个存储库包含所有项目。包含所有内容的中央存储库无法更改,但有一些方法可以确保一次只能访问一个项目。要在本地创建存储库,请运行init命令。您可以在您的主目录中创建它,如下所示,或者在您本地的任何地方。$cvs-d~/sandboxinitCVS允许您将选项传递给cvs命令本身或传递给init子命令。出现在cvs命令之后的选项默认是全局的,而出现在子命令之后的选项是特定于子命令的。在上面显示的示例中,-d标志是一个全局选项。这是为了告诉CVS我们要在何处创建存储库路径,但通常-d标志是指我们要使用的现有存储库位置。一直使用-d标志是乏味的,所以改为设置CVSROOT环境变量。由于我们只在本地工作,我们可以只使用-d选项传递路径,但也可以包含主机名。此命令在您的主目录中创建一个名为sandbox的目录。如果您列出沙箱内容,您会在下面找到一个名为CVSROOT的目录。请不要将此目录与我们的环境变量混淆,后者保存存储库的管理文件。恭喜!您刚刚创建了第一个CVS存储库。签入代码假设您决定保留您最喜欢的颜色的列表。由于您是一个有艺术倾向但健忘的人,因此您输入了颜色列表并将其保存到名为favorites.txt的文件中:blueorangegreendefinitelynotyellow我们还假设您将文件保存到名为colors的目录中。现在您想将您最喜欢的颜色列表置于版本控制之下,因为从现在起五十年后回顾您的品味如何随时间发生变化将会很有趣。为此,您必须将目录导入为新的CVS项目。您可以使用导入命令:$cvs-d~/sandboximport-m""colorscolorsinitialNcolors/favorites.txtNoconflictscreatedbythisimport这里我们再次使用-d标志来指定存储库的位置,其余参数传递给import子命令。必须提供消息,但此处没有必要,因此将其留空。下一个参数colors指定存储库中新目录的名称。此处给出的名称与签入目录的名称相同。最后两个参数分别指定“vendor”和“release”标签。稍后我们将讨论标签。我们刚刚将颜色项目拉入CVS存储库。将代码导入CVS的方法有很多种,但这是《Pragmatic Version Control Using CVS》推荐的方法,《CVS程序员实用指南》。使用此方法的尴尬之处在于您必须重新签出正在签出的工作项目,即使颜色项目已经存在。不要使用这个目录,先删除它,然后从CVS中检出以前的版本,如下:也称为颜色。在此目录中,您会找到源文件favorites.txt和一个名为CVS的目录。这个CVS目录基本上等同于每个Git存储库的.git目录。进行更改并为旅行做准备。和Git一样,CVS也有状态命令:$cvsstatuscvsstatus:Examining.=======================================================================文件:favorites.txt状态:最新工作修订:1.1。1.12018-07-0619:27:54-0400存储库修订版:1.1.1.1/Users/sinclairtarget/sandbox/colors/favorites.txt,v提交标识符:fD7GYxt035GNg8JA粘性标签:(无)粘性日期:(无)粘性选项:(无)这是事情开始变得奇怪的地方。CVS没有提交对象的概念。如上图,有个东西叫做“CommitIdentifier”,不过这个可能是较新版本的标识符,2003年出版的《Pragmatic Version Control Using CVS》一书中没有提到“commitidentifier”的概念。(最新版本CVS于2008年发布。5)在Git中,当我们谈论文件版本时,我们实际上是在谈论与提交45de392相关的内容,而CVS中的文件是独立版本的。该文件的第一个版本是1.1版,下一个是1.2版,依此类推。涉及分支机构时,附加分机号码。所以你会看到如上图1.1.1.1的内容,就是例子的版本号,即使我们没有创建分支,好像也是默认添加的。一个项目中有很多文件和很多提交。如果你运行cvslog命令(相当于gitlog),你会看到每个文件的提交历史信息。在同一个项目中,可能有一个版本为1.2的文件和一个版本为1.14的文件。继续,我们对1.1版本的favorites.txt文件做一些修改(LCTT译注:这里原来的例子是错误的):blueorangegreenanddefinitelynotyellow修改完成后,可以运行cvsdiff看看CVS发生了什么:$cvsdiffcvsdiff:Diffing.Index:favorites.txt=========================================================================RCS文件:/Users/sinclairtarget/sandbox/colors/favorites.txt,vretrievingrevision1.1.1.1diff-r1.1.1.1favorites.txt3a4>cyanCVS识别我们我在包含颜色“cyan”的文件中添加了一个新行。(实际上,它说我们已经对“RCS”文件进行了更改;如您所见,CVS仍在使用RCS。)这种差异指的是当前工作目录中的favorites.txt副本之间的差异和1.1。1.1版文件之间的差异。为了更新存储库中的版本,我们必须提交更改。在Git中,此操作需要几个步骤。首先,更改被暂存,因此它出现在索引中,然后更改被提交,最后,为了让更改对其他人可见,我们必须将提交推送到源存储库。在CVS中,你只需要运行cvscommit命令就可以搞定一切。CVS将汇总它找到的更改并将它们放入存储库:$cvscommit-m"Addcyantofavorites."cvs提交:检查./Users/sinclairtarget/sandbox/colors/favorites.txt,v<--favorites.txt新版本:1.2;上次修订:1.1习惯了Git,这样的操作会吓到我。因为没有更改暂存区的机制,所以您在工作目录中触摸的任何内容都会一次性提交到公共存储库。你有没有因为心烦意乱而私下改写同事糟糕的功能实现,但只是为了发泄情绪,不想让他知道?太糟糕了,如果你不小心提交了,他会认为你是个混蛋。在推送之前,您也无法对提交进行编辑,因为提交就是推送。还是你愿意花40分钟反复运行gitrebase-i命令,让本地的提交历史像数学证明一样清晰严谨?不幸的是,CVS不支持它,因此,每个人都会看到您没有先编写测试用例。不过,现在我终于明白为什么那么多人认为Git不必那么复杂了。对于习惯了直接cvscommit的人来说,stagechanges和pushchanges确实是一件毫无意义的苦差事。人们常说Git是一个“分布式”系统,其中分布式和非分布式的主要区别是:在CVS中,本地提交是不可能的。commit操作是将代码提交到中央仓库,所以没有网络连接,你无法执行操作,你本地的只是你的工作目录;在Git中,会有一个完整的本地仓库,因此即使网络断开,你也可以不间断地执行提交操作。您还可以编辑这些提交、还原、分支,并选择您想要的内容,没有人知道的比他们必须知道的更多。因为提交是如此重要,所以CVS用户很少进行提交。提交可以包含与我们今天在具有十次提交的拉取请求中看到的一样多的内容更改。当提交触发CI构建和自动化测试过程时尤其如此。现在我们运行cvsstatus,我们将看到一个新版本的文件:$cvsstatuscvsstatus:Examining.=========================================================================文件:收藏夹.txt状态:最新工作修订:1.22018-07-0621:18:59-0400存储库修订:1.2/Users/sinclairtarget/sandbox/colors/favorites.txt,v提交标识符:pQx5ooyNk90wW8JA粘性标签:(none)StickyDate:(none)StickyOptions:(none)Merge如上所述,在CVS中,您可以同时编辑其他人正在编辑的文件。这是CVS相对于RCS的重大改进。当需要将更改的部件放回原处时会发生什么?假设您邀请了一些朋友将他们最喜欢的颜色添加到您的列表中。在添加它们时,您决定不再喜欢绿色,并将其从列表中删除。当你提交更新时,你会发现CVS报告了一个问题:$cvscommit-m"Removegreen"cvscommit:Examining.cvscommit:Up-to-datecheckfailedfor`favorites.txt'cvs[commitaborted]:先更正以上错误!这看起来像朋友首先提交了他们的更改。所以你的favorites.txt文件版本没有更新到存储库中的最新版本。这时候运行cvsstatus可以看到本地的favorites.txt文件copy有一些本地变化,是1.2版本,而repository上的版本号是1.3,如下:$cvsstatuscvsstatus:Examining.===================================================================文件:favorites.txt状态:需要合并工作修订:1.22018-07-0710:42:43-0400存储库修订:1.3/Users/sinclairtarget/sandbox/colors/favorites.txt,vCommitIdentifier:2oZ6n0G13bDaldJAStickyTag:(none)StickyDate:(none)StickyOptions:(none)您可以运行cvsdiff查看版本1.2和版本1.3之间的确切区别:$cvsdiff-rHEADfavorites.txtIndex:favorites.txt=========================================================================RCS文件:/Users/sinclairtarget/sandbox/colors/favorites。txt,vretrievingrevision1.3diff-r1.3favorites.txt3d2