说到版本控制工具很多人可能都会马上想到 CVS 和 Subversion,但自从开始使用 git 以后,我在自己的开发过程中都会优先选择 git 而非前者。
最早从今年初就已经开始用 git。刚开始的时候会的确会感到 git 比较复杂,一个原因是它不同于 Subversion 这样的集中式版本控制系统,在 Subversion 中只有一个仓库(repository),许多个工作目录(working copy),而像 git 这样的分部式版本控制系统中,每一个工作目录都包含一个完整仓库,仓库之间内容可能不相同,可以进行仓库之间的同步。另一个原因是 git 的命令非常之多,而它本身的概念也比较复杂(虽然 Linus 说git 是 stupid contenc tracker,但其实这个东西不适合傻瓜使用),还分 repository, index, working tree 等,直接使用也会比较麻烦些,所以我实际一直都是使用 cogito,只有必要的时候才直接使用 git。
为什么要使用分布式的版本控制系统?Subversion 有什么不好?
我最开始使用 Subversion 时一直觉得有一点很不爽,如果我想把某个已有的项目使用Subversion 来进行管理,首先要建立一个仓库,然后把文件 import 到仓库,最后再check out,然后在 check out 的工作目录中再进行修改。为什么要那么麻烦?我只是自己一个人进行开发而已,为什么非要有一个仓库?此其一,只是不爽而已。
第二点使我没有办法使用 Subversion,不得不寻找其他的工具。我要在几台电脑上同时进行开发,我希望在每一台电脑上都能使用版本控制工具。所以我需要有一个放在优盘上的仓库,这个时候使用 Subversion 就有问题了。一来当你提交时你必须得把优盘插上电脑,每次提交都得插上;二来仓库在优盘上的位置不能改变,否则路径改变的话使用 file 协议拷贝出来的工作目录就废了。(我查过 svn propset 的帮助,似乎可以改变仓库地址,但我不会,网上也没有搜到。)
这两个问题 git 都可以很好的解决(严格来说我使用的是 cogito)。要把已有的文件加入版本控制的话使用 cg init 一条命令即可。而分布式的版本控制系统解决第二个问题实在是再适合不过了。在优盘上建立一个仓库,不同机器上的仓库在开发时就尽管 commit 到本地的仓库好了,在要换机器之前先把修改 push 到优盘上的仓库,到其他机器上时 pull 出来然和 merge 一下就好了,cogito 可以直接使用 update 完成这两步操作。而优盘上仓库路径如果有改变的话可以使用 cg-branch-chg 很方便的修改远程仓库的地址。实际可以认为优盘上的仓库就是一个中央仓库,所以有许多个仓库其实并不是一件可怕的事情,也完全可以像使用集中式的版本控制系统那样自定一个为中央仓库即可。但分布式的版本控制系统不强制你这么做,给你更多的灵活性。
更加让我喜欢 git 的是它的 branch 概念。我在使用 Subversion 的时候从来没有用过,因为它的 branch 概念是通过 copy 来实现的(当然不是实际的拷贝),不够直观。目前我只用 branch 来进行实验性的开发。而 Linus使用 git 管理内核开发时通过 branch 来整合多人所做的修改,内核有那么多的 branch,Linus 通过 git 可以很轻松的 merge 这些不同的 branch 所做的修改,最后从他自己的仓库中发布新版本的 Linux 内核。
此外 git 对磁盘空间的利用也更高效(不过需要定期对仓库使用 git repack -d 命令以后),其他方面性能也都很出色。想想它要管理 Linux 内核那么大的项目就可以知道了。
Linus 在 Google Tech talk 上做过 git 的介绍,以及他是如何使用 git 来管理内核开发的。他的演讲里面对分布式版本控制系统的好处有更好的说明。不过 Linus 自己也承认自己是个 strong opinion person,它在演讲的时候多次说集中式的版本控制系统没有前途,因此 Subversion 的开发者想要开发一个更好的 CVS 其实是脑子出了毛病,实在是太 offensive 了,好在他是 Linus,大家都知道他的个性。(他还说过自己是 digust pig, and proud of it,汗啊……)
但是,但是……
git 很好,可是它不跨平台,至少在非 Linux 平台上运行的没有那么好,在非 Linux 文件系统上会有麻烦。我虽然不在 Windows 上做开发,但是最近要在 Solaris 上做开发,我不想花时间在 Solaris 上把 git 装起来,而且如果以后如果要和其他使用 Windows 的人合作的话我可不想再使用 Subversion。所以我需要一个替代 git 的工具。这篇文章介绍了 Mozilla“移向”新版本控制工具时是如何做出选择。(原文强调是 “move” 而不是 “pick”,因为最后的候选者都很好。)首先肯定要用分布式的,然后在 4 个分布式的版本控制工具中筛选,git 和 Monotone 因为支持平台问题而被排除,剩下 Bazaar 和 Mercurial。前者有 Canonicol 在支持。而后者已经是 OpenSolaris 等著名项目的版本控制工具,而且有着非常好的文档,可以很方便的使用 python 的 web server 发布项目。在 Mozilla 的版本控制工具选择中 Mercurial 最终因为性能而胜出。所以我也决定转到 Mercurial 去了,看了看文档,感觉和 cogito 很像,比 git 更简单,迁移过程应该会比较顺利。
另外提一下,分布式的版本控制工具还有 darcs, arch。前者是用 Haskell 写的,后者据说很复杂。而 git 则是受到 Monotone 的影响。