GIT和CVS之间的差异

jmp7cifd  于 2022-12-25  发布在  Git
关注(0)|答案(5)|浏览(152)

Git和CVS版本控制系统的区别是什么?
我已经愉快地使用CVS超过10年了,现在我被告知Git要好得多。有人能解释一下两者之间的区别吗?为什么一个比另一个好?

cetgtptt

cetgtptt1#

主要的区别是(正如在其他回复中已经说过的)CVS是(旧的)集中式版本控制系统,而Git是分布式的。
但是,即使您在单机(单账户)上为单个开发人员使用版本控制,Git和CVS之间还是有一些区别:

*设置仓库. Git将仓库存储在项目顶层目录的.git目录中; CVS需要设置CVSROOT,这是一个存储不同项目(模块)版本控制信息的中心位置。这种设计对用户来说的结果是,将现有源代码导入版本控制就像Git中的“git init && git add . && git commit”一样简单,而在CVS中则要复杂得多。
*原子操作。因为CVS在开始时是一组围绕每个文件的RCS版本控制系统的脚本,所以提交(和其他操作)在CVS中不是原子的;如果对仓库的操作中途中断,仓库将处于不一致的状态。在Git中,所有操作都是原子的:他们要么整体上成功,要么毫无变化地失败。
*Changesets. CVS中的更改是针对每个文件的,而Git中的更改(提交)总是针对整个项目。这是非常重要的“范式转变”。其后果之一是在Git中很容易恢复(创建一个可撤消的更改)或撤消“整个”更改;另一个结果是在CVS中很容易进行部分 checkout ,而目前在Git中几乎是不可能的。更改是按文件进行的,这一事实导致了CVS中提交消息的GNU Changelog格式的发明; Git用户使用(一些Git工具期望)不同的约定,用单行描述(总结)更改,然后是空行,最后是更详细的更改描述。
*命名修订/版本号。在CVS中,更改是按文件进行的,这一事实还存在另一个问题:版本号(正如你有时在 keyword expansion 中看到的,见下文),比如1.4反映了给定文件被修改的次数。在Git中,项目的每个版本(每次提交)都有一个唯一的名字,由SHA-1 id给出;通常前7-8个字符就足以识别一个提交(在分布式版本控制系统中,你不能使用简单的版本编号方案--这需要集中的编号授权)。在CVS中,版本号或符号名称引用整个项目的状态,你可以使用标签;在Git中也是如此,如果你想在某个项目版本中使用'v1.5.6-rc 2'这样的名称...但是Git中的标记更容易使用。
*容易分支. CVS中的分支在我看来过于复杂,而且很难处理。你必须标记分支来为整个存储库分支命名(如果我没记错的话,在某些情况下,即使这样也会失败,因为每个文件都需要处理)再加上CVS没有 merge tracking,所以你要么记住,要么手动标记合并和分支点,并且手动提供正确的信息给“cvs update -j”来合并分支,这使得分支变得不必要的困难。在Git中创建和合并分支是非常容易的; Git会自己记住所有需要的信息(所以合并分支就像“git merge branchname”一样简单)...它必须这样做,因为分布式开发自然会导致多个分支。

这意味着您可以使用 * 主题分支 *,即在单独的特性分支中通过多个步骤开发单独的特性。

*重命名(和复制)跟踪. CVS不支持文件重命名,手动重命名可能会将历史记录一分为二,或导致无效的历史记录,无法正确恢复重命名前的项目状态。Git使用启发式重命名检测,基于内容和文件名的相似性(此解决方案在实践中效果很好)。您也可以请求检测文件的复制。这意味着:

  • 当检查指定的提交时你会得到一些文件被重命名的信息,
  • 正确合并会考虑重命名(例如,如果文件只在一个分支中重命名)
  • “git deflect”是“cvs annotate”的(更好的)等价物,它是一个显示文件内容的逐行历史记录的工具,也可以在重命名之间跟随代码移动

*二进制文件. CVS对二进制文件的支持非常有限(例如图像),要求用户在添加时明确标记二进制文件(或稍后使用“cvs admin”,或通过wrappers根据文件名自动完成),以避免通过行尾转换和关键字扩展损坏二进制文件。Git会根据内容自动检测二进制文件,方式与CNU diff和其他工具相同;你可以使用gitattributes机制来覆盖这个检测。此外,由于默认为'safecrlf'(事实上,你必须请求行末转换,尽管这可能是默认打开的,具体取决于发行版),二进制文件对于不可恢复的损坏是安全的,并且(有限的)关键字扩展在Git中是一个严格的'opt-in'。
*Keyword expansion. Git提供的关键字与CVS相比非常非常有限(默认情况下)。这是因为两个事实:Git中的更改是针对仓库而不是针对文件的,并且Git避免在切换到其他分支或回退到历史中的其他点时修改没有更改的文件。如果您想使用Git嵌入修订号,您应该使用您的构建系统来完成,例如下面的Linux内核源代码和Git源代码中的GIT-VERSION-GEN脚本示例。
修改提交.因为在分布式VCS(如Git)中, 发布 * 的行为与创建提交是分开的,所以用户可以更改(编辑,重写)历史记录中未发布的部分,而不会给其他用户带来不便。特别是当您注意到打印错误时(或其他错误),或提交中的错误,你可以简单地使用“git commit --amend”。2这在CVS中是不可能的(至少没有大量的黑客攻击)。
*更多的工具. Git提供了比CVS更多的工具。其中一个更重要的是“git bisect“,它可以用来查找引入bug的提交(修订);如果你的提交很小并且是自包含的,那么发现bug在哪里应该是相当容易的。

如果你和至少一个其他开发者合作,你会发现Git和CVS之间有以下不同之处:

*在合并前提交Git使用 commit-before-merge,而不是像CVS那样使用 merge-before-commit(或 update-then-commit)。如果您正在编辑文件,准备创建新的提交(新修订)某人在相同分支上创建了新提交并且它现在在仓库中,CVS会强制你在提交之前先更新工作目录并解决冲突。Git则不是这样。你首先提交,在版本控制中保存你的状态,然后合并其他开发人员的更改。2您也可以要求其他开发人员进行合并并解决冲突。

如果你更喜欢线性历史,避免合并,你可以通过“git rebase”(和“git pull --rebase”)使用 commit-merge-recommit 工作流,这与CVS类似,你可以在更新后的状态上重放你的修改,但是你总是先提交。

*不需要中央存储库使用Git,您不需要在一个中央位置提交更改。每个开发人员都可以拥有自己的存储库(或者更好的存储库:私有的一个,他/她在其中进行开发,而公有的一个,她/他在其中发布已经准备好的部分),并且他们可以从彼此的存储库中拉/取,以对称的方式。另一方面,对于更大的项目来说,通常有 * 社会 * 定义/指定的中央存储库,每个人都从其中拉(从其中获取更改)。

最后,当需要与大量开发人员协作时,Git提供了更多的可能性。下面是针对不同兴趣阶段和项目位置(使用CVS或Git进行版本控制)的CVS在Git中的差异:

*lurker.如果您只对从项目中获取最新的变更感兴趣,(不传播您的变更),或者做 private 开发(不对原始项目做出贡献);或者您使用外国项目作为自己项目的基础(更改是本地的,发布它们没有意义)。

Git在这里支持***匿名未经认证的***只读访问,通过自定义高效的git://协议,或者如果你在防火墙后面阻止DEFAULT_GIT_PORT(9418),你可以使用普通HTTP。
对于CVS,最常见的只读访问解决方案(据我所知)是CVS_AUTH_PORT(2401)上的“pserver”协议的***guest帐户***,通常称为“anonymous”,密码为空。凭据默认存储在$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-ing一种拉取请求。

主要开发人员,即直接发布其变更的人员(到主/规范存储库)。这一类别对于分布式版本控制系统更为广泛,因为拥有多个对中央存储库具有写访问权限的开发人员不仅是可能的工作流(您可以有一个维护者将更改推送到规范存储库,一组他/她从中拉取更改的副维护者/子系统维护者,以及通过邮件将补丁发送到维护者/项目邮件列表或发送到副维护者/子维护者之一的广泛的LEAF开发者)。

使用Git时,你可以选择使用SSH协议(git协议封装在SSH中)发布更改,使用诸如“git shell”(帮助安全,限制shell帐户的访问)或Gitosis(管理访问而不需要单独的shell帐户)等工具,以及使用HTTPS和WebDAV,使用普通HTTP认证。
使用CVS时,可以选择自定义 * 未加密(纯文本)*pserver协议,或使用远程shell(在这里您确实应该使用SSH)来发布您的变更,对于 * 集中式 * 版本控制系统来说,这意味着提交您的变更(创建提交)。你也可以使用SSH通过'pserver'协议,而且有他们的工具自动化这...但我不认为这是容易的,因为例如Gitosis。
一般来说,分布式版本控制系统,如Git,提供了更广泛的工作流选择;而集中式版本控制系统,如CVS,则需要区分拥有仓库提交权限的用户和没有提交权限的用户,CVS没有提供任何工具来帮助接受没有提交权限的用户的贡献(通过补丁)。
Karl Fogel在Producing Open Source Software中关于版本控制的章节中指出,最好不要对允许对公共存储库进行更改的区域提供过于严格、僵化和严密的控制;(为此)依靠社会限制(如代码审查)比依靠技术限制要好得多;分布式版本控制系统进一步减少了IMHO...

j5fpnvbx

j5fpnvbx2#

The Git website可能是最好的解释。
我最喜欢的功能是离线时也能提交。还有速度,除了推和拉之外,其他所有操作都能以极快的速度进行。(这些操作都是非破坏性的,所以如果你的中央存储库滞后,你可以在喝咖啡时推/拉。)另一个好处是它自带电池:内置的gitk是一个足够好的历史查看器; git gui是一个足够好的提交工具; git add -igit add -pgit rebase -i是输出彩色化的良好交互界面;如果您不想/不能摆弄中央存储库,git daemongit instaweb对于临时协作来说已经足够好了。

nxagd54h

nxagd54h3#

Git是DVCS,而CVS是一个集中式的。简单描述如下:当你没有连接到多个可能的存储库中的任何一个时,你可以得到版本控制的所有好处,而且操作速度更快。

iyfjxgzm

iyfjxgzm4#

我也是一个10年以上的cvs快乐用户,虽然我也喜欢git,而且随着时间的推移会更喜欢它,虽然我目前工作的大多数项目都使用cvs或svn,而且我们似乎无法说服我工作的地方的官僚们让我们在防火墙上打一个git漏洞。
有两个东西使cvs比其他的更好,一个是cvsps,另一个是AndrewMorton的补丁脚本,或者说quilt,Cvsps允许你把一个提交的多个文件重组成一个补丁(从而从CVS中提取“变更集”)虽然quilt或Andrew Morton的补丁脚本允许您非常轻松地将合理的“变更集”提交到CVS中,允许您同时处理多个事情,同时在提交之前保持它们的分离。CVS有它的怪癖,但我已经习惯了其中的大多数。

xwbd5t1u

xwbd5t1u5#

“愉快地使用CVS超过x年”,是一个有趣的想法:-)这是一个巨大的进步,从保持大量的副本,但是...
我猜你已经习惯了它的怪癖,或者没有做太多的分支和合并。
你的组织中的人已经习惯了简历的局限性,你的工作实践也相应地进行了调整;
例如,从不让多于一个的开发者一次对一个包工作,仅在紧急情况下使用分支等。
基本原则是,事情越困难,做的人越少。

相关问题