赞
踩
最近新项目的版本控制工具从Mercurial更换到了Git。在学习和尝试使用Git的过程中,难免产生疑问。为什么不继续使用Mercurial而改用Git?
虽然Git相比Mercurial显然更流行,但流行从来就不是更换工具的原因。本文希望从分析Git的优势来说服自己,为什么应该在新项目切换到Git作为版本控制工具。这也算是一种心路历程吧。
学习Git时首先感受到的不同是暂存区(Staging Area)的存在。为什么要增加这么个步骤?这样做显然在commit的时候要多一步git stage。虽然git commit -a可以做到两步合一,但是多这么一步,设计者一定有他的用意。思考了之前使用Mercurial实践中遇到的问题,我逐渐能理解这个区域的作用。
首先,从通用层面说,这样做可以提醒自己什么改动预备commit,什么不是。如果一个改动我打算在新一版中commit,那么我需要手动将其stage到暂存区。这可以看作是一种软件帮助完善work flow的行为。之前在工作中,有时会临时用sed替换环境文件中开关选项,这些改动并不需要被commit记录。使用Mercurial话,默认做法会导致你有可能误push这样的改动,而Git的暂存区需要你有意识的stage需要commit的文件。所以除非你非常确定自己在做什么,否则不应该无脑使用git commit -a。
其次,暂存区可以当作一种保存阶段性工作的方式。当对文件的改动还不足以达到一次commit的粒度,但又算是阶段性成果时;或者改动尚未验证正确性时,暂存区可以充当一种缓存的存在。在暂存之后,我尽可以继续完善之前的修改,又或者尝试一个临时的想法。因为暂存区的存在,我可以非常方便的把暂存区的版本与工作目录下的版本进行比较,把它们两者与改动前版本进行对比;或者对暂存区和工作目录文件独立的使用撤销操作,也可以吧暂存区的快照恢复到工作目录。如果使用Mercurial,恐怕要么我需要commit一个中间版本,要么通过cp文件的方式保存多个版本的改动。有了暂存区,尝试临时的想法也变成了一个轻量级的操作。
另外,由于有暂存区的存在,在解决merge冲突时可以通过stage冲突文件来标记冲突已解决,相对来说比hg resolve方便直观。
这个问题下面也有很多前辈回答了不少深层次的原因和好处。
为什么要先 git add 才能 git commit ?www.zhihu.comMercurial通过changesets存储文件的改动,这种做法被称作基于差异(delta-based)的版本控制。这种做法显然的好处是大部分情况下占用空间较小,同时很容易比较两个版本之间的差异。另外,在工作中经常需要看某行代码的改动是哪个changeset中进行的(如使用hg blame),Mercurial在查看此类信息时效率很高。
扯远了,继续说Git。Git使用完全不同的方法存储文件改动:通过存储文件快照(snapshot)来保存文件状态。这种方式导致比较不同版本文件差异时,总是要从头完全进行diff操作。而这种基于快照的存储方式,则为Git的分支管理提供了巨大的益处。
Git的分支是一个非常轻量级的概念,每个分支可以理解为一个指针,指向对应版本的提交对象。由于Git使用快照去存储文件,切换分支的代价非常小:找到目标分支指针指向的提交对象,把这个版本的文件快照恢复到工作区即可。我怀疑Git在最初设计时,正是因为对分支管理的强烈需求,而使用了快照机制。
也正因为Git的分支强大且方便,Git认为做任何代码修改都应该处在某个分支下。在使用Mercurial时,我用hg up命令可以很方便的切换工作目录的文件到任意版本。在Git中,最接近的命令是git checkout <SHA-1>, 不过这个命令会让你处于"detached HEAD"状态:
这种状态其实有些风险,因为如果在这个状态下commit了改动,没有任何一个分支指针指向新push的版本,很有可能会忘记这个版本。最好是通过新建一个分支(哪怕是临时分支)来指向某个历史版本的方式,实现这个功能。这其实是一种思维方式和工作模式的转变。我们应当时刻思考如何利用Git分支管理的便利,来改进工作流程,把工作交给工具来管理。
由于强大的分支,以及暂存区的存在,Git的常用命令不可避免的比Mercurial多且复杂。为此Git提供了详尽的命令提示。比如git status会提示你如果取消暂存区的改动,如果丢弃工作区的改动等。
当输入命令错误时,也会智能提示可能的命令:
所以总的来说还算对新手友好。
Git与Mercurial相比,暂存区的存在和分支管理的特性是它们最大的不同(以我粗浅的、表面的认识)。使用Git最主要是为了其分支模型,这是我认为对Mercurial最大的优势。对于公司的项目来说,文件会长期处于多个用户共同维护。并且过去的项目实践证明,对多个分支(比如多个stable/dev/bug fix分支)长期共存有着强烈的需求。因此引入Git代替Mercurial来改善工作流程,减少人为操作,减轻维护人员工作量,有着非常直接的帮助。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。