GIT和CVS的区别
Git和CVS版本控制系统有什么区别?
我一直很高兴地使用CVS十多年了,现在我被告知Git好多了。 有人能解释一下这两者之间的区别是什么,为什么一个比另一个好?
主要区别在于(正如其他回复中已经说过的那样),CVS是(旧的)集中版本控制系统,而Git是分布式的。
但是即使你对单一开发者使用版本控制,在单一机器(单一帐户)上,Git和CVS之间也有一些差异:
-
设置存储库 。 Git将仓库存储在项目顶部目录的
.git
目录中; CVS需要设置CVSROOT,这是存储不同项目(模块)的版本控制信息的中心位置。 这个devise对于用户的后果是把现有的源文件导入到版本控制中就像Git中的“git init && git add。&& git commit”一样简单,而在CVS中更加复杂 。 -
primefaces操作 。 由于CVS在开始时是一套围绕每个文件的RCS版本控制系统的脚本,所以提交(和其他操作)在CVS中不是primefaces的; 如果存储库上的操作在中间被中断,则存储库可能处于不一致的状态。 在Git中,所有的操作都是primefaces的:要么是整体成功的,要么是没有任何改变而失败。
-
更改集 。 CVS的变化是每个文件,而在Git中的变化(提交)他们总是引用整个项目。 这是非常重要的范式转变 。 其中一个后果就是Git非常容易恢复(创build一个撤消的变化)或者撤销整个变化; 其他的结果是在CVS中很容易做到部分签出,而目前在Git中是不可能的。 事实上,每个文件的变化被分组在一起导致在CVS中提交消息的GNU Changelog格式的发明; Git用户使用(和一些Git工具期望的)不同的约定,用单行描述(汇总)变化,然后是空行,然后是更详细的变化描述。
-
命名修订/版本号 。 还有一个问题与CVS更改中的每个文件有关:版本号(如有时在关键字扩展中看到的,请参见下文),如1.4反映给定文件已更改多less次。 在Git中,整个项目的每个版本(每个提交)都有其唯一的名称,由SHA-1 ID给出; 通常前7-8个字符足以识别提交(分布式版本控制系统中的版本不能使用简单的编号scheme – 需要中央编号权限)。 在CVS中,版本号或符号名称是指整个项目的状态,您可以使用标签 ; 在Git中也是如此,如果你想在一个项目的某个版本中使用像'v1.5.6-rc2'这样的名字…但是Git中的标签更容易使用。
-
容易分支 。 在我看来,CVS分支过于复杂,难以处理。 你必须标记分支来为整个存储库分支命名(甚至在某些情况下,如果我没有记错,由于每个文件的处理,可能会失败)。 除此之外,CVS没有合并跟踪 ,所以你必须记住,或者手动标记合并和分支点,并手动提供“cvs update -j”的合适信息来合并分支,并且使分支不必要的很难使用。 在Git创build和合并分支是很容易的; Git自己记得所有需要的信息(所以合并一个分支就像“git merge branchname ”一样简单)……它不得不这样做,因为分布式开发自然会导致多个分支。
这意味着您可以使用主题分支 ,即在单独的function分支中以多个步骤开发单独的function。
-
重命名(和复制)跟踪 。 CVS不支持文件重命名,手动重命名可能会将历史logging分为两部分,或导致无效的历史logging,无法在重命名之前正确恢复项目的状态。 Git使用启发式重命名检测,基于内容和文件名的相似性(该解决scheme在实践中运行良好)。 您也可以请求检测文件的复制。 这意味着:
- 当检查指定的提交时,你会得到一些文件被重命名的信息,
- 合并正确地将重命名考虑在内(例如,如果该文件只在一个分支中重命名)
- “git blame”,(更好的)相当于“cvs annotate”,一个显示文件内容的逐行历史的工具,可以在代码移动之后也跨越重命名
-
二进制文件 。 CVS对二进制文件(例如图像)的支持非常有限,要求用户在添加(或者稍后使用“cvs admin”,或者通过包装自动根据文件名自动执行时)时显式地标记二进制文件,以避免二进制文件通过行结束转换和关键字扩展。 Git根据内容自动检测二进制文件,就像CNU diff和其他工具一样; 您可以使用gitattributes机制覆盖此检测。 此外,二进制文件是安全的,因为默认的'safecrlf'(以及事实上,你必须要求行尾转换,尽pipe这可能是默认情况下打开取决于分布),不可恢复的mangling,而(有限)关键字在Git中扩展是一个严格的“select”。
-
关键字扩展 。 与CVS相比,Git提供了非常非常有限的一组关键字(默认情况下)。 这是因为两个事实:Git中的更改是每个存储库而不是每个文件,Git避免修改切换到其他分支或倒回到历史中其他点的文件。 如果你想使用Gitembedded修订版本号,你应该使用你的编译系统来完成这个工作,例如在Linux内核源代码和Git源文件中使用GIT-VERSION-GEN脚本。
-
修改提交 。 因为在分布式VCS(如Git)中, 发布行为与创build提交是分开的,所以可以改变(编辑,重写)未发布的历史logging部分,而不会给其他用户带来不便。 特别是如果你注意到提交信息中的错字(或其他错误),或提交错误,你可以简单地使用“git commit –amend”。 这在CVS中是不可能的(至less不是没有沉重的嘲弄)。
-
更多的工具 。 Git提供了比CVS更多的工具。 其中一个更重要的是“ git bisect ”,它可以用来find引入bug的提交(修订) 如果你的提交很小并且自成一体,那么应该相当容易findbug。
如果您与至less一个其他开发人员合作,您会发现Git和CVS之间还存在以下差异:
-
在合并之前提交 Git使用commit-before-merge而不是像CVS一样, merge-before-commit (或者update-then-commit )。 如果在编辑文件时,准备创build新的提交(新版本),其他人在同一分支上创build了新的提交,并且现在在存储库中,CVS强制您首先更新工作目录并解决冲突,然后再允许您提交。 Git的情况并非如此。 您首先提交,在版本控制中保存状态,然后合并其他开发人员更改。 您也可以要求其他开发人员进行合并并解决冲突。
如果你喜欢线性历史并避免合并,你总是可以通过“git rebase”(和“git pull –rebase”)来使用commit-merge-recommit工作stream,类似于CVS,你可以在上面重放你的改变的更新状态。 但是你总是首先承诺。
-
不需要中央存储库使用Git,不需要有一个中心的地方提交您的更改。 每个开发人员都可以拥有自己的存储库(或者更好的存储库:私有存储库,公开发布那个已准备好的部分),并且可以从其他存储库中取出/取出对称的时尚。 另一方面,大型项目通常会有一个社会定义/提名的中央存储库,每个人都从中获取(从中获取更改)。
最后,当需要与大量开发人员合作时,Git提供了更多的可能性。 在Git中,对于不同的感兴趣的阶段和项目中的位置(在使用CVS或Git的版本控制下),下面是CVS之间的区别:
-
潜伏者 。 如果你只想从项目中获得最新的变化( 不传播你的变化 ),或者做私人开发(不回馈原始项目); 或者你使用外国项目作为你自己项目的基础(变化是本地的,发布它们是没有意义的)。
Git支持通过自定义高效的
git://
协议进行匿名未经身份validation的只读访问,或者如果您在防火墙后面阻止DEFAULT_GIT_PORT
(9418),则可以使用普通HTTP。对于CVS最常见的解决scheme(据我所知)的只读访问是
CVS_AUTH_PORT
(2401)上的'pserver'协议的访客账户 ,通常被称为“匿名”并且为空密码。 凭证默认存储在$HOME/.cvspass
文件中,所以您只需提供一次; 但是,这还是有点障碍的(你必须知道guest账户的名字,或者注意CVS服务器的消息)和烦恼。 -
边缘开发者(叶贡献者) 。 在OSS中传播更改的一种方法是通过电子邮件发送补丁程序 。 这是最常见的解决scheme,如果你是(或多或less)偶然的开发人员,发送单个更改或单个错误修正。 BTW。 发送补丁可能是通过审查委员会(补丁审查系统)或类似的手段,不仅通过电子邮件。
Git在这里提供的工具可以帮助发送者(客户端)和维护者(服务器)的传播(发布)机制。 对于希望通过电子邮件发送更改的用户,可以使用“ git rebase ”(或“git pull –rebase”)工具在当前上游版本之上重播您自己的更改,以便您的更改位于当前版本之上)和“ git format-patch ”创build具有提交信息(和作者身份)的电子邮件,以(扩展的)统一差异格式(加diffstat以便于查看)的forms进行更改。 维护者可以直接将这样的邮件转换为使用“ git am ”保存所有信息(包括提交信息)的提交。
CVS不提供这样的工具:你可以使用“cvs diff”/“cvs rdiff”来生成更改,并使用GNU补丁来应用更改,但据我所知,无法自动应用提交消息。 CVS是为了在客户端服务器中使用…
-
中尉 。 如果你是一个项目(子系统)的独立部分的维护者,或者你的项目的开发遵循Linux内核开发中使用的“信任networking”工作stream程,或者如果你有自己的公共存储库,那么你想要发布太大的通过电子邮件发送补丁系列 ,你可以发送拉请求到项目的(主要)维护者。
这是针对分布式版本控制系统的解决scheme,所以CVS当然不支持这种协作方式。 甚至有一个名为“git request-pull”的工具,它可以帮助您准备发送给维护人员的电子邮件,请求从您的存储库中提取。 感谢“git bundle”,即使没有公共存储库,也可以通过电子邮件或sneakernet发送更改。 一些像GitHub这样的Git托pipe站点支持通知某个人正在工作(发布了一些工作)(如果他/她使用相同的Git托pipe站点),并为PM提供一种拉取请求。
-
主要开发者 ,即直接发布他/她的改变(到主/规范库)的人。 这个类别对于分布式版本控制系统来说更广泛,因为拥有多个开发人员可以对中央存储库进行写入访问,这不仅是可能的工作stream程(您可以让单个维护人员将更改推送到规范存储库,一组中间人/子系统维护人员通过邮件发送修补程序的维护人员/项目邮件列表或者其中的一个副主pipe)。
使用Git,您可以select使用SSH协议 (git协议封装在SSH中)来发布更改,使用诸如“git shell”(帮助安全,限制shell帐户访问)或Gitosis (pipe理访问而不需要单独的shell帐户)和带有WebDAV的HTTPS ,并具有普通的HTTP身份validation。
使用CVS,可以在自定义未encryption(纯文本) pserver协议或使用远程shell (实际上应该使用SSH的地方 )之间select发布更改,这对于集中版本控制系统来说意味着提交更改(创build提交)。 那么,你也可以使用SSH隧道“pserver”协议,并有党的工具自动化…但我不认为这是像Gitosis一样简单。
通常,分布式版本控制系统(如Git)提供了更广泛的可能工作stream程select。 使用集中式版本控制系统(如CVS),必须要区分具有对存储库的提交访问权限的人员,以及没有…的人员,CVS不提供任何工具来帮助接受来自人员的贡献(通过补丁)提交访问。
卡尔·福格尔(Karl Fogel)在“ 开源软件的制作”一节中提到版本控制时指出,最好不要对允许更改公共存储库的领域提供过于严格,严格和严格的控制; 依靠社交限制(比如代码审查)而不是技术限制要好得多; 分布式版本控制系统甚至进一步减less恕我直言…
HTH (希望帮助)
Linus(git的原始作者)的这个讲话几乎总结了它。
Google技术讲座:Git上的Linus Torvalds
注意:高度评价的谈话。
Git是一个DVCS ,而不是CVS是一个集中的。 简单的描述将是:当你没有连接到多个可能的存储库时,你将获得版本控制的所有好处,而且操作速度更快。
Git网站可能是最好的解释。
我的宠物function可以在离线时进行提交。 速度,除推拉之外的所有事情的速度都是惊人的速度。 (而且这些操作在devise上是非破坏性的,所以如果你的中央回购滞后,你可以推/拉咖啡。)另一个好处是,它包括电池包括:内置gitk
是一个足够好的历史观众; git gui
是一个很好的提交工具; 与输出彩色, git add -i
, git add -p
, git rebase -i
是足够好的交互界面; git daemon
和git instaweb
对于特别的协作是足够的,如果你不想/不能摆弄你的中央仓库。
我也是一个十年以上的CVS用户,虽然我也喜欢Git,但是随着时间的推移,我仍然会喜欢它,尽pipe我目前使用的大多数项目都使用CVS或svn,而我们似乎无法在我工作的地方取得了信任,让我们通过防火墙打出一个git-hole。
一些使cvs比cvsps更好的东西,另外一个是Andrew Morton的补丁脚本或者被子。 Cvsps允许您在提交时将一个提交的多个文件重新组合成一个补丁(并从CVS中提取“变更集”),或者Andrew Morton的补丁脚本允许您轻松,舒适地将敏感的“变更集”提交到cvs中,同时处理多个事物,同时在提交之前保持分离。 CVS有它的怪癖,但是我已经习惯了其中的大部分。
“快乐地使用CVS超过x年”,是一个有趣的想法:-)从保持大量的副本,这是一个巨大的进步,但…
我猜你已经习惯了所有的怪癖,或者不做太多的分支和合并。 有更糟糕的可能性;
你组织中的人已经习惯了CVS的限制,你的工作做法也相应地适应了;
例如,一次只能有一个开发者在一个包上工作,只能在紧急情况下使用分支等。
基本的原则是越难,就越less。