git 取消merge_我为什么该用Git而不是Mercurial?

01e92c653d8588b284b6d34aa9ef566f.png

最近新项目的版本控制工具从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文件的方式保存多个版本的改动。有了暂存区,尝试临时的想法也变成了一个轻量级的操作。

26f4fbb9fb35c39189807a2b84307dac.png

8d6fba43e3b8cd8e71de7d84f79cd4a8.png

另外,由于有暂存区的存在,在解决merge冲突时可以通过stage冲突文件来标记冲突已解决,相对来说比hg resolve方便直观。

这个问题下面也有很多前辈回答了不少深层次的原因和好处。

为什么要先 git add 才能 git commit ?​www.zhihu.com

快照机制与分支管理

Mercurial通过changesets存储文件的改动,这种做法被称作基于差异(delta-based)的版本控制。这种做法显然的好处是大部分情况下占用空间较小,同时很容易比较两个版本之间的差异。另外,在工作中经常需要看某行代码的改动是哪个changeset中进行的(如使用hg blame),Mercurial在查看此类信息时效率很高。

扯远了,继续说Git。Git使用完全不同的方法存储文件改动:通过存储文件快照(snapshot)来保存文件状态。这种方式导致比较不同版本文件差异时,总是要从头完全进行diff操作。而这种基于快照的存储方式,则为Git的分支管理提供了巨大的益处。

Git的分支是一个非常轻量级的概念,每个分支可以理解为一个指针,指向对应版本的提交对象。由于Git使用快照去存储文件,切换分支的代价非常小:找到目标分支指针指向的提交对象,把这个版本的文件快照恢复到工作区即可。我怀疑Git在最初设计时,正是因为对分支管理的强烈需求,而使用了快照机制。

43e2cd81af1373f25a09a41b343da334.png
来自Pro Git中对Git历史的介绍

也正因为Git的分支强大且方便,Git认为做任何代码修改都应该处在某个分支下。在使用Mercurial时,我用hg up命令可以很方便的切换工作目录的文件到任意版本。在Git中,最接近的命令是git checkout <SHA-1>, 不过这个命令会让你处于"detached HEAD"状态:

fa9eee842d8eefbda305d94e65b32ab3.png
detached HEAD状态

这种状态其实有些风险,因为如果在这个状态下commit了改动,没有任何一个分支指针指向新push的版本,很有可能会忘记这个版本。最好是通过新建一个分支(哪怕是临时分支)来指向某个历史版本的方式,实现这个功能。这其实是一种思维方式和工作模式的转变。我们应当时刻思考如何利用Git分支管理的便利,来改进工作流程,把工作交给工具来管理。

命令提示

由于强大的分支,以及暂存区的存在,Git的常用命令不可避免的比Mercurial多且复杂。为此Git提供了详尽的命令提示。比如git status会提示你如果取消暂存区的改动,如果丢弃工作区的改动等。

165d38621d1d18edacb35d472ce90e03.png
git会提示有效的命令

当输入命令错误时,也会智能提示可能的命令:

f72d0de401b78567aa3e7e9a663abe67.png
git会提示最相似的命令

所以总的来说还算对新手友好。

总结

Git与Mercurial相比,暂存区的存在和分支管理的特性是它们最大的不同(以我粗浅的、表面的认识)。使用Git最主要是为了其分支模型,这是我认为对Mercurial最大的优势。对于公司的项目来说,文件会长期处于多个用户共同维护。并且过去的项目实践证明,对多个分支(比如多个stable/dev/bug fix分支)长期共存有着强烈的需求。因此引入Git代替Mercurial来改善工作流程,减少人为操作,减轻维护人员工作量,有着非常直接的帮助。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值