版本控制(又称修订控制)。
考虑以下问题。你正在与他人合作的项目中共享文件。你们俩都需要编辑一个名为“WhateverController.java”的大文件。
最原始的处理方式是不同时编辑该文件,但这时你们俩必须保持一致。当你有一个团队时,尤其是如果团队有数十、数百或数千名成员(在开源项目中很常见),那么这就完全不可能了。
早期,解决这个问题的原始“方法”是使用签出/签入机制。当你需要编辑文件时,“签出”文件,文件被锁定,直到你“签入”它后才能进行编辑。这是通过适当的软件实现的,例如微软耐人寻味的垃圾软件SourceSafe。但是如果有人忘记了“签入”文件,则在使用该文件时其他人无法编辑该文件。然后有人去度假或以其他原因离开项目,结果就是无休止的混乱、困惑,通常还会丢失大量的代码。这增加了巨大的管理工作。
接着出现了CVS,随后是Subversion,作者称其为“正确的CVS”,因此CVS和Subversion本质上是相同的想法。对于这些工具,实际上没有签出操作。你只需编辑需要的文件并进行签入。请注意,实际文件存储在中央服务器上,每个用户还在自己的工作站上运行软件。这个位置在服务器上被称为仓库。
那么,如果两个人在CVS/Subversion上都在操作同一个文件呢?它们将会被合并,通常使用GNU diff和patch。'diff'是一个提取两个文件之间差异的实用程序。'patch'使用此类'diff'文件来修补其他文件。
如果你正在一个函数中修改 WhateverController.java 文件,而我也在同一文件的另一个函数中修改该文件,当你完成你的工作后,你只需将更改提交,这些更改会应用于服务器上的文件。同时,我本地的拷贝不知道你的更改,因此你的更改对我的代码没有任何影响。当我完成我的更改后,我也将文件检入。但是现在我们有了这个看似复杂的情况。
让我们把原始的 WhateverController.java 文件称为文件 A。
你编辑该文件,得到的结果是文件 B。
我在不同的位置编辑了相同的文件,没有使用你的更改,这个文件是文件 C。
现在我们似乎有了一个问题。文件 B 和 C 的更改都是针对文件 A 的更改。所以在像 SourceSafe 或 Dreamweaver 这样的荒唐程序中,通常会覆盖文件 B 的更改(因为它先被检入)。
CVS/Subversion 和可能 Git(我对 Git 几乎一无所知)生成补丁而不是仅覆盖文件。
文件 A 和 C 之间的差异会产生并形成补丁 X。文件 A 和 B 之间的差异会产生并形成补丁 Y。
然后将补丁 X 和 Y 应用于文件 A,这样最终的结果就是文件 A 加上我们各自工作站上对 B 和 C 进行的更改。
通常这样做是完美无缺的。有时我们可能会在同一段代码中工作,此时 CVS/Subversion 将通知程序员出现了问题,并在文件中呈现出该问题。这些问题通常很容易解决,至少我从来没有遇到过什么麻烦。图形化工具例如 Visual Studio、Project Builder(Mac OS X)等通常会显示两个文件和冲突,这样你就可以选择保留哪些行和丢弃哪些行,如果需要手动合并冲突,也可以手动编辑文件。
因此,源代码控制本质上是解决多人同时对同一文件进行修改的问题的解决方案。基本上就是这样。
希望这能解释清楚。
编辑:像Subversion和可能的Git这样的良好源代码控制系统还有许多其他好处。 如果出现问题,您可以回到其他版本,因此您不必手动备份所有内容。 实际上,至少使用Subversion,如果我搞砸了什么或者想查看旧版本的代码,我可以这样做而不会干扰任何其他人的工作。