Git 简明指南

Git & Github 介绍

Git首先是一个版本控制系统,它可以持续的追踪你的文件变化情况,从而通过Git,你可以将编辑过的文件恢复到之前的状态,也可以方便查看编辑前后文件内容的差异。

同时,Git也是一个分布式的版本控制系统,对于用户来说,主要体现在允许多个用户协同开发,同时修改代码库。

Github则是一个可以托管代码的平台,同时提供了Web的管理界面和一系列相关的开发服务和功能,功能稳定速度较快,所以在其上托管的项目非常之多,所以用来作为我们的项目托管平台应该是最好的选择。

下载安装

有各种各样的工具可以实现Git的功能,但是由于我们主要采用Github作为托管平台,首先推荐的就是Github自己的图形界面工具: Github Desktop

命令行下只要安装Git就可以了。

事实上,目前大部分的IDE都自带或者通过插件实现了Git的所有功能,像:IntelliJ的所有IDE(包括Android Studio),Visual Studio, Sublime Text等等。

具体的使用方法请自行谷歌。其实只要掌握了基本的Git命令,各种工具其实都大同小异。

Git基本概念

首先每个都有一个远端服务器仓库,所有的代码都会最终被提交到这里。开发环境中每个开发者都会有一个本地的代码仓库,由于新的代码通常是被开发者首先添加到本地代码仓库中,然后在提交到远端服务器上,所以本地代码的版本通常都要比远端服务器新。但是,如果有其他开发者提交了新的代码到远端服务器,那么这个时候Git就会告诉你,你本地的代码落后于远端服务器版本了,那么你可以选择是否下载最新的版本。

除了开发环境,一个完整的环节应该还包括测试和生产环境,这两个环境的代码都应该对应于远端服务器中的某一个比较完善的版本,远远落后于服务器上的最新版本。且通常只下载代码,不提交代码,也就是它不会对服务器上的版本做任何的改变。这两个环境与我们的项目都关系不大。

新建或者下载一个本地仓库

如果你已经有了一个本地项目,想要使用Git进行版本控制(哪怕你只是新建了一个空的文件夹,还没有任何代码也可以),这个时候你只需要使用命令:

git init

就可以创建一个新的Git仓库了。

如果你的项目已经有了一个远程的项目仓库(例如我们的代码库是:git@github.com:saukymo/Parkinson_Health.git),那么我们只需要复制一份远端代码库到本地就可以了,使用命令:

git clone git@github.com:yubozu/Parkinson_Health.git

此时,默认下载的最新版本的代码,当然你也可以选择下载某一特定版本的代码,这里不多说。

本地仓库

本地仓库由三个部分组成,首先是你的工作目录,里面是你的实际项目文件,例如代码、配置等等,第二个是暂存区(stage),它像是一个缓存区域,你可以随时将修改过的文件添加到暂存区里来,对于这些文件的最新改动都会被记录下来,你可以随时查看它们和之前的区别(diff)。最后一个就是你的版本树(HEAD)了,你需要将暂存区里的改动提交到这里来(commit),此时就好像给你的项目照了一个快照,目前所有的状态都被保存到了版本树的最前面了。

需要注意的是,暂存区和版本树都是用户不可见的(通常保存在项目根目录的.git文件夹中),所以你可以放心的修改你的代码而不会影响到git的功能。

一般工作流程

首先,我们直接在修改本地工作目录的代码即可,开发过程与平时完全一样。当你完成一个阶段的开发(或者开发完一个小的功能,或者到了一定时间需要休息一下)时,这时就需要通过Git来提交你之前做的修改了。

git status

首先你需要查看一下本地文件的状态。

git status

这时你将看到你的项目文件中,有哪些被添加到了暂存区中,有哪些还没有(通常是新增加的文件,因为一般来说,一个文件只要被添加到暂存区中一次,它就会一直在暂存区中,不用每次都添加进来)。

git diff

然后你可以通过

git diff

来查看你对这些文件做了哪些修改,改动都是放在一起显示的,红色的代表以前的状态,绿色代表现在的状态。由于这些改动都是你刚刚进行的,所以应该有比较深的印象,这时你应该简单的浏览一遍,回顾一下你做了哪些改动,有没有遗漏(例如 TODO)或者多余的修改(例如 调试时多余的输出等)。

diff过程命令行下不是很方便,这时候通过IDE自带的比对工具会方便一些。

git commit

确认无误后,你就可以提交你的代码了,使用命令

git commit 

commit的时候需要填写你本次提交做了哪些修改,这样之后自己和别人查看时能很快了解这次提交做了哪些修改。

以上做的所有步骤都是在本地进行的,改动的也只是你的本地代码仓库。如果你仅仅需要一个版本控制功能,那么到这一步就可以了,但是我们的项目是托管在远端服务器上的,所以我们还需要将本地的修改提交到远端服务器上,这样其他人也就能获得和使用我们的代码了。

如果改动不多,我们也可以用一条命令完成提交(commit)

git commit -m "This is an example commit comment."

git push

使用命令

git push

这条命令就会将你之前在本地代码仓库进行的所有提交(commit)一次性全部添加到远程代码仓库上去。

分支

本篇教程不会写关于冲突的处理,但需要了解的是,当两个甚至多个人对同一块代码进行改动的时候,会出现冲突的情况。如果大家一直都在一起改,那么每次提交都会有冲突的可能,这样显然是效率很低的。所以,为了尽量使不同开发者之间的开发不互相影响,Git有一个分支的概念。

当你新建仓库的时候,默认是在"master"分支上的,你可以新建一个新的分支,在新的分支上进行开发,此时这个新分支只有你一个人在开发,是完全独立于其他开发人员的,当开发完成后,再将它们合并(merge)到主分支上(可以是master,也可以是任何约定好的分支)。这样,只有在最后合并(merge)的时候才需要处理冲突的情况。

新建分支

通过以下命令可以新建一个名字为new_branch的branch,在你第一次提交(push)代码到远端服务器上之前,这个分支不会被其他人看到。

git branch new_branch

列出和切换分支

git branch -l
git checkout new_branch

第一个命令可以列出本地代码有哪些分支,第二个命令可以切换到任意一个分支。

提交分支到远端服务器

当你在这个分支上的修改完成后,你可以先按照前面的一般工作流程进行操作,当你第一次输入git push后,git会告诉你说这个分支在远端服务器没有对应的分支。此时你可以使用:

git push origin new_branch

来设置这个分支对应的远端分支(分支采用相同的名字),之后再提交更改的时候,直接使用git push即可。

合并代码

当你的功能开发完成之后,可以到Github网站上去提交一个合并申请(pull request),此时其他成员就会收到你的申请,他们也可以看到你这次更新所做的所有修改。

此时,不管你有没有权限进行服务器端的合并(merge)操作,都建议你留一些时间(1~2天)给其他开发者,让他们来审核你的代码(Code review)。这个过程不仅能提高项目的代码质量,也是一个很好的学习编程的方式。所以,也建议你在看到其他人的合并申请(pull request)时,主动的去review他们的代码,并留下自己的comments。

删除分支

由于我们采用基于分支的开发流程,pull request被合并之后,会自动删除分支,所以一般不需要这个命令,但有时候我们可能会不小心新建一个分支,那么就可以用下面这个命令:

git branch -d new_branch

更新与合并

如果你要与其他人合作开发,在你每次开始工作前,都应该检查其他人是否有提交新的代码,如果有的话,你应该先将他们的代码下载下来。使用命令:

git pull

此时,会将远端的最新代码覆盖到本地,那么这里有个潜在的可能会要处理冲突。

但是,按照我们的开发流程,我们不会提交代码到master分支,其他分支都是自己所独有的。所以理论上这个操作仅仅是更新代码到最新的版本,而不需要处理冲突。

回滚代码

希望你永远不需要用到这个部分的功能。当你需要回到之前的某个版本时,使用命令:

git reset --hard 

此时所有没有提交的改动都会还原到上一次提交的地方。

再往前的回滚一般不会用到。

写在最后

基于Git的开发是现在最基本的开发流程,不管是用来管理个人项目,还是协同开发都是非常好用的,希望大家都能很快的掌握。学习过程肯定是很痛苦的,但是熟悉和习惯之后这些额外的操作其实代价非常小,甚至可以将commit操作当做保存操作一样频繁的使用。

其实这个流程对于我们这样的小团队来说,略微有一点点复杂了,但是这个流程最重要的地方其实是进行Code review。这个流程给每个人Review团队中其他人代码的机会,正如前文所说,这个过程既提高了代码质量,也提高了自己的编程水平。目前这个Review的过程不是必须的,但是希望大家都能积极的参与进来。

最后,这个指南肯定会有各种各样的错误和疏(sheng)漏(lue),如果有遇到任何的问题,我们可以一起解决。如果有任何的建议,我们也可以再讨论,做出改进。

最后的最后,希望大家能够善于利用搜索引擎来解决编程方面的问题。如果可以报销的话,可以为大家提供谷(fan)歌(qiang)的解决方案。

参考文献

设计很棒的Git教程