Git和CVS版本控制系统有什么区别?
我使用CVS已有10多年了,现在我被告知Git更好。有人可以解释一下两者之间的区别是什么,为什么一个比另一个更好?
Git和CVS版本控制系统有什么区别?
我使用CVS已有10多年了,现在我被告知Git更好。有人可以解释一下两者之间的区别是什么,为什么一个比另一个更好?
Answers:
主要区别在于(正如在其他答复中已经提到的那样),CVS是(旧的)集中式版本控制系统,而Git是分布式的。
但是,即使您对单个开发人员使用版本控制,也可以在单个计算机(单个帐户)上使用Git和CVS之间存在一些差异:
建立仓库。Git将存储库存储在.git
项目顶层目录中;CVS需要设置CVSROOT,这是用于存储不同项目(模块)的版本控制信息的中央位置。这种为用户设计的结果是,将现有源导入版本控制就像在Git中“ git init && git add。&& git commit”一样简单,而在CVS中则更为复杂。
原子操作。因为开始时CVS是围绕每个文件的RCS版本控制系统的一组脚本,所以提交(和其他操作)在CVS中不是原子的。如果对存储库的操作在中间中断,则存储库可能处于不一致状态。在Git中,所有操作都是原子的:要么整体成功,要么失败而没有任何更改。
变更集。CVS中的更改是针对每个文件的,而Git中的更改(提交)始终引用整个项目。这是非常重要的范式转换。其后果之一是,在Git中很容易还原(创建要撤消的更改)或撤消整个更改。另一个结果是,在CVS中,很容易进行部分检出,而在Git中,这几乎是不可能的。更改是按文件组合在一起的事实导致了GNU Changelog格式的发明,用于CVS中的提交消息。Git用户使用(并且有些Git工具期望)不同的约定,其中一行描述(总结)更改,后跟空白行,然后是更详细的更改描述。
命名版本/版本号。还有一个问题与事实有关,即CVS中的更改是针对每个文件的:版本号(如您有时在关键字扩展中看到的,请参见下文)(如1.4)反映了给定文件更改了多少时间。在Git中,整个项目的每个版本(每次提交)都有其唯一的名称(由SHA-1 id给出);通常,前7-8个字符足以标识一次提交(对于分布式版本控制系统中的版本,您不能使用简单的编号方案-需要中央编号权限)。在CVS中,使用版本号或符号名称来引用整个项目的状态,您可以使用标签; 如果您想在项目的某些版本中使用“ v1.5.6-rc2”之类的名称,则在Git中也是如此,但是Git中的标签更易于使用。
易于分支。我认为CVS中的分支过于复杂,难以处理。您必须标记分支以具有整个存储库分支的名称(如果我没记错的话,由于每个文件的处理,即使在某些情况下也可能失败)。此外,CVS没有合并跟踪,因此您必须记住或手动标记合并和分支点,并手动为“ cvs update -j”提供正确的信息以合并分支,这使得分支成为可能。不必要的难用。在Git中,创建和合并分支非常容易。Git会自己记住所有必需的信息(因此合并分支就像“ git merge branchname ” 一样简单)……因为分布式开发自然会导致多个分支,所以它必须这样做。
这意味着您可以使用主题分支,即在单独的功能分支中的多个步骤中开发单独的功能。
重命名(并复制)跟踪。CVS不支持文件重命名,并且手动重命名可能会将历史记录分成两部分,或者导致无效的历史记录,从而使您无法在重命名之前正确恢复项目的状态。Git根据内容和文件名的相似性使用启发式重命名检测(此解决方案在实践中效果很好)。您还可以请求检测文件复制。这意味着:
二进制文件。CVS对二进制文件(例如图像)的支持非常有限,要求用户在添加时(或稍后使用“ cvs admin”或通过包装器根据文件名自动进行标记)显式标记二进制文件,以避免对通过行尾转换和关键字扩展生成二进制文件。Git以与CNU diff和其他工具相同的方式基于内容自动检测二进制文件。您可以使用gitattributes机制覆盖此检测。此外,由于使用了'safecrlf'的默认设置(以及您必须请求行尾转换(尽管默认情况下可能会根据发行情况启用此功能),并且该关键字(受限)),因此二进制文件可以防止不可恢复的损坏扩展是Git中严格的“选择加入”。
关键字扩展。与CVS相比,Git提供的关键字非常有限(默认情况下)。这是由于两个事实:Git中的更改是针对每个存储库而不是每个文件,并且Git避免了修改切换到其他分支或倒退到历史记录其他位置时未更改的文件。如果要使用Git嵌入修订号,则应使用自己的构建系统来执行此操作,例如,以下Linux内核源代码和Git源代码中的GIT-VERSION-GEN脚本示例。
修改提交。因为在Git之类的分布式VCS中,发布行为与创建提交是分开的,所以可以更改(编辑,重写)历史的未发布部分,而不会给其他用户带来麻烦。特别是如果您在提交消息中发现拼写错误(或其他错误),或者在提交中存在错误,则只需使用“ git commit --amend”。在CVS中,这是不可能的(至少没有重型黑客的支持)。
更多工具。Git提供的工具比CVS多得多。更重要的一个是“ git bisect ”,可用于查找引入错误的提交(修订)。如果您的提交很小并且是独立的,那么应该很容易发现错误所在。
如果您与至少一名其他开发人员合作,那么您还会发现Git和CVS之间存在以下差异:
合并前提交 Git使用的是commit-before-merge,而不是像CVS那样使用merge-before-commit(或update-then-commit)。如果在编辑文件时准备创建新的提交(新修订),而其他人在同一分支上创建了新的提交,而现在又在存储库中,则CVS会强制您首先更新工作目录并解决冲突,然后再允许提交。Git并非如此。您首先提交,将状态保存在版本控制中,然后合并其他开发人员更改。您还可以要求其他开发人员进行合并并解决冲突。
如果您希望具有线性历史记录并避免合并,则始终可以通过“ git rebase”(和“ git pull --rebase”)使用commit-merge-recommit工作流,这与CVS类似,因为您可以在顶部重播更改状态更新。但是你总是先犯。
不需要中央存储库使用Git,无需在单个中央位置提交更改。每个开发人员都可以拥有自己的存储库(或更好的存储库:在其中进行开发的私有存储库,在其发布已准备好的部分的公共存储库中公开),并且他们可以从彼此的存储库中提取/获取信息。对称时尚。另一方面,大型项目通常具有社会定义/指定的中央存储库,每个人都可以从中获取(从中获取更改)。
最终,当需要与大量开发人员合作时,Git提供了更多的可能性。下面是针对项目的不同兴趣阶段和职位的Git中CVS之间的区别(在使用CVS或Git的版本控制下):
潜伏者。如果您只对从项目中获取最新更改感兴趣(不传播更改),或者进行私有开发(不回馈原始项目);或者您将外国项目用作自己项目的基础(更改是本地的,发布这些更改没有意义)。
Git在这里通过自定义高效协议支持匿名的未经身份验证的只读访问git://
,或者如果您处于防火墙阻止DEFAULT_GIT_PORT
之下(9418),则可以使用纯HTTP。
对于CVS,对只读访问最常见的解决方案(据我所知)是(2401)上“ pserver”协议的来宾帐户CVS_AUTH_PORT
,通常称为“匿名”,密码为空。凭据默认存储在$HOME/.cvspass
文件中,因此您只需提供一次即可;尽管如此,这还是有一定的障碍(您必须知道来宾帐户的名称,或者注意CVS服务器消息)和烦恼。
边缘开发人员(叶贡献者)。传播OSS更改的一种方法是通过电子邮件发送补丁。如果您(或多或少)是偶然的开发人员,发送单个更改或单个错误修正,则这是最常见的解决方案。顺便说一句。发送补丁程序可能是通过审核委员会(补丁程序审核系统)或类似方式,而不仅是通过电子邮件。
Git在这里提供了一些工具,可以帮助发送者(客户端)和维护者(服务器)实现这种传播(发布)机制。对于想要通过电子邮件发送更改的人,有一个“ git rebase ”(或“ git pull --rebase”)工具可以在当前上游版本的基础上重放您自己的更改,因此您的更改位于当前版本的基础上(新鲜)和“ git format-patch ”来创建带有提交消息(和作者身份)的电子邮件,并以(扩展的)统一的diff格式(加上diffstat便于查看)的形式进行更改。维护人员可以使用“ git am ” 将此类电子邮件直接转换为提交,以保留所有信息(包括提交消息)。
CVS没有提供这样的工具:您可以使用“ cvs diff” /“ cvs rdiff”生成更改,并使用GNU补丁来应用更改,但是据我所知,没有办法自动应用提交消息。CVS旨在以客户端<->服务器方式使用...
中尉。如果您是项目(子系统)各个部分的维护者,或者您的项目开发遵循的是Linux内核开发中使用的“信任网络”工作流程...或者只是您拥有自己的公共存储库,而您所做的更改如果要发布太大而无法通过电子邮件作为补丁程序系列发送,则可以将拉取请求发送到项目的(主要)维护者。
这是特定于分布式版本控制系统的解决方案,因此CVS当然不支持这种协作方式。甚至还有一个名为“ git request-pull”的工具,它可以帮助准备要发送给维护者的电子邮件,其中包含从存储库中提取请求的请求。多亏了“ git bundle”,您甚至可以在没有公共存储库的情况下使用此机制,方法是通过电子邮件或sneakernet发送更改包。一些Git托管站点(例如GitHub)支持通知某人正在您的项目上工作(发布了一些作品)(前提是他/她使用了相同的Git托管站点),并支持PM提出一种拉取请求。
主要开发人员,即直接发布其更改(到主/规范库)的人员。此类别对于分布式版本控制系统而言范围更广,因为让多个开发人员具有对中央存储库的写访问权限不仅是可能的工作流程(您可以有一个将标准变更推送到标准存储库的维护人员,也可以是他/她从中的一组中尉/子系统维护人员。拉,以及广泛的叶子开发人员,他们通过邮件将补丁发送到维护者/项目邮件列表,或发给中尉/子维护者之一。
使用Git,您可以选择使用SSH协议(封装在SSH中的git协议)来发布更改,并使用“ git shell”(帮助提高安全性,限制对shell帐户的访问)或Gitosis(无需单独的shell帐户即可管理访问)之类的工具),以及带有WebDAV的HTTPS(具有普通的HTTP身份验证)。
使用CVS,可以在自定义未加密(纯文本) pserver协议之间进行选择,也可以使用远程外壳(实际上应该使用SSH)发布更改,对于集中式版本控制系统,这意味着提交更改(创建提交)。嗯,您还可以使用SSH隧道化“ pserver”协议,并且有第三方工具可以自动执行此操作……但是我认为这不像Gitosis那样简单。
在一般的分布式版本控制系统中,例如Git,提供了更多可能的工作流选择。使用集中式版本控制系统(例如CVS),您必须区分具有提交访问存储库权限的人员和没有权限访问...的人员,并且CVS不提供任何工具来帮助接受(但不通过)补丁的人员提交访问权限。
Karl Fogel在“ 生产开源软件”中有关版本控制的部分中指出,最好不要在允许更改公共存储库的区域上提供过于严格,严格和严格的控制;(为此)依靠社会限制(例如代码审查)比依靠技术限制要好得多;分布式版本控制系统进一步减少了恕我直言...
HTH (希望有帮助)
Git是DVCS,而CVS是集中式。简单的描述将是:当您不连接到多个可能的存储库中的任何一个时,您将获得版本控制的所有好处,而且操作速度更快。
我也是10岁以上的cvs用户,虽然我也喜欢git,但随着时间的推移,我会更喜欢它,尽管我目前从事的大多数项目目前都使用cvs或svn,但我们似乎无法为了让大家知道我在哪里工作,让我们在防火墙上打了一个鬼洞。
cvsps可以使cvs变得比以前更好,而cvsps可以使cvs变得更好,另一件事是Andrew Morton的补丁脚本或quilt。Cvsps允许您将提交的多个文件重构为一个补丁(从而从CVS中提取“变更集”),而被子或Andrew Morton的补丁脚本可以使您轻松,轻松地将明智的“变更集”提交到cv中,从而使您可以同时处理多种事物,同时在提交之前仍将它们分开。CVS有其独特之处,但我已经习惯了大多数。