用Git管理你的代码

寒假回到家里,生活节奏一下子慢下来,我也仿佛突然多了一些回顾、总结的机会,过去几年的时间里,我陆续接触到一些很好的科研助力工具,这些工具有的是学术软件,有的是在线社区……无一不令我有相见恨晚之感。我打算利用空闲的时间,将这些得力工具一一介绍出来,供感兴趣的朋友参考。
作为系列文章的第一篇,我决定从Git开始。

背景介绍

对于一个经常和代码打交道的人来说,版本管理应该不是个陌生的概念,版本管理的最大作用在于它可以记录下代码的一切修改历史,从而一旦出现问题,可以快速找到出错的源头;当然对于多人协作的项目,版本管理更是必不可少的工具。

在众多版本管理工具中,目前最流行的应该是Git,它其实是Linux的创始人Linus为了更好地进行Linux内核开发而设计的版本管理工具,一经问世,便在开源界广受推崇,甚至著名的开源项目托管平台Github就是以此命名的。

我接触Git也是从Github开始,这个网站的设计简洁明了,很好上手,干货很多,而且常常透露出一股幽默劲儿。这是个不可多得的自学宝库,我在这上面长了不少见识,其中之一便是Git版本管理工具。虽然Github时不时会被GFW墙一下(对于GFW封锁一个技术网站的行为我完全无法理解),但我依然会借助各种翻墙工具去那里get一些新技能。

后来,由于有代码托管的需要,我不得不放弃Github的客户端(在GFW的干扰下其同步速度有时候简直慢得令人抓狂),很是无奈。一番寻觅后,一个堪称完美的替代品居然出现了:Bitbucket。后者在设计理念上与Github有着很大的不同,但是作为代码托管平台,它的功能已经非常完善,而且Bitbucket还支持免费的私有仓库(repository),这一点为它加分不少。Bitbucket有一个配套的本地版本管理软件,SourceTree,同时支持Git和Mercurial,本文即以SourceTree为例,简单介绍下如何用Git管理代码。

简单操作

SourceTree很好上手,它提供了Git一系列命令的GUI界面。

首先,「克隆/新建」(clone/new)按钮可以快速建立一个代码仓库,或者克隆一个已有的仓库;所谓仓库,就是一个授权Git监视的代码项目,Git会在对应根目录下建立一个名为「.git」的隐藏文件夹,尔后这个目录下的一切代码变动都会被Git记录下来。在Git的概念中,仓库有两种,一种是本地仓库,一种是远程仓库,像Bitbucket这样的网站就提供了远程仓库的托管;当然如果你仅仅管理自己硬盘上的代码,只用本地仓库也可。

创建好仓库后,就可以提交代码了。具体的提交流程是这样的:你用任意的代码编辑器修改代码后,返回SourceTree,此时SourceTree的「日志/历史」页面的Git图谱会自动出现「未提交的更改」字样,表明新的代码变动被检测到了,然后你点击「提交」(commit)按钮,页面转向「文件状态」,然后选中待定的文件,并在提交评论区输入相应的说明,接着点击页面右下角的「提交」,大功告成。

这就是Git的最简单应用,每次阶段性的代码调试完成后,都可以这么提交一下,Git会自动帮你将这些历史修改都完善地记录下来(精确到代码的行),日后需要查询的话就可以根据时间和提交说明来按图索骥。

假设第二天你想回到之前的代码版本,只需使用「检出」(checkout)功能,就可以返回之前记录的任何一个节点。

建立分支

以上仅仅是Git的单线程用法,Git的强大之处其实在于分支管理,不过由于我用的不多,只能略讲一二:假设我们现在已经搭建好主程序,然后需要若干子程序供调用。直接的想法是挨个写子程序,写好一个就提交一次,直到最终写完,但是这样的话,一旦子程序过多,我们便有可能自己搞糊涂先提交了哪个后提交了哪个,因为它们在单线程的逻辑上并无先后次序。一个更合理的方式是将这若干子程序的开发并列处理,大家谁也不比谁优先,同时进行开发,怎么做?用Git的「分支」(branch)功能。

Git建立仓库后有一个默认分支,叫做「master」,这是主分支,严格的程序开发者通常不会轻易变动主分支,而是划分出一系列子分支来进行具体的代码管理。对于我自己来说,由于平时也涉及不到大型程序开发,所以master也会经常变动,我并不觉得危险,但在进行子程序开发时,为了自己保持逻辑清晰,我还是会果断采用Git的分支功能。

这里需要注意一点,建立分支后,这个分支的一切操作都应该是与其他分支无关的,这一点非常关键。比如你就不能在A分支中随随便便就把B分支必需的文件给删了,否则如果B分支没有及时更新这个文件的话,那么合并到主分支后,B中的那个重要的文件就不存在了。我头一次犯这样的错误还腹诽了一下Git的设计,认为它不够智能——其实不是工具不智能,而是用工具的人思路不清晰罢了。分支功能本来就是为了提供一个并行不悖的开发环境而设定的,各个分支内的修改提交本就应该独立无关,你非要在这个分支里修改另一个分支的内容,不乱套才怪。所以有空要多写写程序,可以让你的思维变得更有条理。

说完了分支,接下来就是「合并」(merge)了,这个功能很好理解,指的是子分支开发完了,现在需要合并到主分支去。这里,我建议勾选SourceTree的「选项」菜单里「Git」选项卡中的「合并时不要使用快进方式,总是创建提交」候选项,如此,每次合并后,就会新建一个新的节点,便于日后查看。与「合并」类似的,还有「变基」功能,不过我用得不多,等以后更熟悉了再补充。

远程仓库

以上都是本地仓库的操作,在大多数时候就够用了,然而,如果你经常要在两个地方工作,比如宿舍和实验室,那么远程仓库就很有必要了,它可以保证你的代码永远处于最新状态;并且所有修改都存在云端,不用怕硬盘坏掉(顺带一提,我这人是个典型的同步控,喜欢搜集研究各种同步、备份工具,如果不是考虑到隐私问题,我可能已经把我所有的文件资料都放在云端了)。建立远程仓库可用Github平台或者Bitbucket平台,前者是全开源的,后者则提供私有仓库。

有关远程仓库的命令主要有两个:「拉取」(pull)和「推送」(push),前者是从远程仓库将代码更改同步到本地仓库,后者反之。具体使用时,最好遵循先拉后推的原则,以免出现冲突;这个习惯养好了,以后跟别人协作也不会出岔子。

关于代码版本冲突的问题,一开始遇到可能会不知所措。不必担心,Git有着比较完善的代码分析工具,可以明白标示出不同版本的差异之处,只是需要你花时间去比对罢了。或者用方便的「使用我的版本」和「使用他人版本」来快速解决(前提是你清楚哪个版本是你想要的);当然出现版本冲突问题,往往还是你写程序时逻辑没理顺导致的。所以,再好的工具,也只能帮你提高做事的效率,而无法代替你做本份内的事情。

关于Git,就先说这么多,我人懒,就不截图手把手地教了,这篇文字主要是介绍一个基于Git的版本管理概念和基本操作流程,你若有兴趣,去下载SourceTree,建立一个仓库花上两小时试一试,一切就都明白了。

  1. Hi, 我是Bitbucket的设计师之一,可以与你跟进多了解下你的体验吗?

      • 与非
      • 2016年7月25日

      可以哈,不过我用到的功能都比较简单,属于入门级的。
      我常用的邮箱是yufeiee[at]gmail.com,欢迎联系。

  1. No trackbacks yet.

Steven 发表评论 取消回复