Git与项目管理

引言

GitHub作为目前全球最大的开源代码托管平台,上面托管了大量优质的开源代码。相信很多人都用过,但是不是所有人都对GitHub里的这个Git特别了解。那么面对新人接下来yellowko会依据自己的一些经验做相关的简要介绍,本文不涉及代码,只做一些基础概念上的梳理,以达到能基本使用为目的。至于最后用GUI还是命令行,这些知识都是通的。Git的工作原理和概念有相互关联,yellowko能力有限,无法整理出循序渐进的讲述逻辑,也存在理解不足的情况,可能会有错误,欢迎指正。

Git

版本控制系统

Github最核心的就是对Git的支持,Git是Linux开发者Linus为了管理Linux版本用一个月开发出来的免费、开源的版本控制系统(version control system,VCS)。那什么是版本控制系统呢,要说清楚这个问题,我们先从VCS的来源开始。我们可以设想一些情况,当自己要写一个文档时,每次修订都会产生一个文件,出于某些原因,希望每次修订的文档都能保存,最后出现了一大堆文件;做设计的朋友应该也会出现某某文件最终版、真·最终版等一大堆文件;写代码的同学也会有突然代码不能用了,又忘记自己改了哪里,无法复原的情况等等。

混乱的文件管理

这还只是单个文件的版本管理的情况,一旦面对整个项目,这种管理方式简直是灾难。为了解决这些问题,出现了VCS,在VCS中只需保存一份文件,之后VCS会自动追踪你所做的每次修改,通过相关软件,可以对比各文件版本之间的差异,随时切换到任何版本。对于文本类的文件,例如代码,通过可视化软件可以非常方便地对比任意两个版本之间的增删。这给项目管理带来了很大的便利。

Git的工作方式

致力于快速上手,没必要深入了解Git的工作原理,但是了解浅层的原理及框架能够在使用时更得心应手,这是很有必要的。大框架上Git是一个支持分布式的系统,引用一张Git官网上入门书籍中对于其的描述如图所示,

分布式VCS

版本库通常分为本地和远程两个,两方各玩各的,只有需要进行同步合并时才会进行冲突的解决,由于大家几乎是对称式的设计,除了自己以外的都可以当作远程仓库,是可以完全去中心化的运作模式,服务器的设置纯粹是为了有一个24小时开机的仓库而已。

而每一个Git系统分为五个部分:本地仓库、工作区、暂存区、储存区附加一个可选项远程仓库。其中前四个都在本地。不考虑复制分支情况下Git的工作的状态转移图如图所示:

Git状态转移图

从远程仓库克隆到本地仓库后,打开文件目录我们看到的就是工作区,其中 .git 隐藏目录就是我们的本地仓库,其中储存了我们克隆下来的仓库内所有的更改。当我们在敲定文件修改后,需要将当前文件做一个快照操作(add,暂存更改),这部分文件就会在暂存区有一个快照,然后再将暂存区文件提交,文件就会进入本地仓库,本地仓库就会对这次更改做记录。这样就完成了一个本地的回环①。

如果需要和远程仓库进行交互,那也可以推送到远程仓库。有时候远程仓库可能也会有修改,想要获取到这部分信息,可以从远程仓库上拉取到本地仓库,这样就完成了一个和远程仓库的回环②。

另一个储藏区的回环③下面再提。

这三个回环各自独立互不干扰。但是这里就引出了一个问题,既然各自独立,但是数据交换时怎么保证同步呢?我们的工作是以第一个回环为主的,保证冲突在工作区解决是最安全的方案,所以解决方案是在从远程仓库拉取或者弹出储藏时将出现的冲突标记到工作区的文件中,在解决了冲突后才能继续操作。

Git中的重要概念

Git里面有几个比较重要的概念:克隆、拉取、推送、提交、暂存、储藏、弹出、分支、指针、签出。掌握了这几个概念基本上就可以应付Git的基本使用了。

Git的版本历史是一个有向无环图,下面有些地方为了简化会称作树,但树只是一种特殊的有向无环图。每个节点都是一个整个工程的快照。各开发者基于同一个初始版本进行开发(当然也有多个个不同项目中途合并的情况,这里只说简单的情况)。如图所示,这是 Vincent Driessen 在博客中展示的一个Git模型,作为入门的指导还是很有意义的。注意,本文中箭头所指的方向均为下一个提交(子节点),有些文章的箭头方向会指向前一个提交(父节点),要注意区分。

Git模型

下面解释一下这其中的几个重点概念,与前一节有内容的交叉,可以对照着看。

克隆(clone):克隆很简单,把整个项目从远程仓库完整复制到本地就叫克隆,可以是一整颗树或者是最近的一些节点。

暂存(stage):前面也有提到每次暂存就是将文件做一个快照。

提交(commit):而提交就是将这个快照作为一个节点连接到修改前所在的节点上。

分支(branch):分支模型可以说是Git最为重要的特性。最简单的开发是线性开发,节点连成一条线,这样是一条分支。但是有时候需要在保证主线正常开发时,希望在支线进行开发,这时候分支模型就发挥了极大的作用,从一个节点上分叉到一个新的分支,开发完成后再合并回去。由于Git在设计时分支切换成本非常低,所以Git官方书籍上非常鼓励开发人员频繁地创建和使用分支来提高项目管理的效率。这样的特性使得Git与多人开发模型十分契合,可以直接应用到多人开发上。

拉取(pull):本地有仓库时会使用拉取而不是克隆,拉取会从远程仓库获取(fetch)一条分支到自己本地的分支上,并与本地的分支合并(merge)。

推送(push):推送和拉取是反动作,会将本地分支推送到远程,与远程分支合并。

储藏(stash):通常会在开发中途需要临时解决其他问题时使用。比如在解决其他紧急问题时需要切换分支,这个时候必须清空工作区,但是当前工作区修改情况并不足以达到一次提交的标准,这时候就需要用到储藏。储藏类似于提交,但是其没有进入版本库中,而是进入了储藏库。

弹出(pop):是储藏的反操作,储藏弹出后不会继续在储藏库中存在,所以储藏是一种临时操作。

指针(pointer):在Git中存在两种指针,一种是分支指针,指向某个提交,另一种是HEAD指针,通常指向某个分支指针,这个时候分支指针后会带一个 ‘*’ 。但是当希望切换到之前的提交节点上时,HEAD就会和分支指针分离,此时HEAD的状态称为游离,当在从中间的节点提交后,会产生一个匿名的分支,这时候HEAD指针指到这个匿名分支的指针上,一定要需要注意的是,由于匿名分支被设计为一个临时分支,如果当HEAD指针从匿名分支上离开或回退时,没有对这个匿名分支命名或者没有合并到已命名分支,那么这个匿名分支上的提交就会丢失!!

签出(checkout):前面提到的从当前分支指针将HEAD指针移走就是签出操作,签出丢弃工作区更改,然后将工作区内容变成指向的提交节点的内容。通常会用于切换分支,也可以切换到之前节点,查看历史版本或者之后从这个节点创建新分支。

至于更多的信息,在Git的使用手册里有详细介绍。

下图描述了一个简单的Git工作流,对上述部分概念做了图形化演示,每个方格表示的是一个分支能看到的节点,有些节点是虚的说明其和其他分支相同节点一样,在一个分支里看到的是一条线,但实际的存储结构是一棵树。如果本地没有创建A到B为从远程克隆一个,D到E演示了一个匿名分支出现的过程,G到H将dev分支的4合并到master分支的3时产生了一个合并后的节点5,H到I推送时仅将master分支推送到了远程的master分支

一个简单的Git工作流

合理的Git树

为了更好地进行项目的管理,一颗健康高效的Git树应该是怎样的呢。在 Vincent Driessen 的博客中有比较详细的描述/,总结后有如下几点:
1. 每次提交解决一个问题,目的是保证每次提交都有意义,也方便做自动化处理。
2. 在master分支上做大版本发布,保证在master分支上的永远是稳定版本。
3. 在develop分支上做小版本发布,独立的develop分支用于新功能的开发,可以防止在开发过程中扰乱稳定版本。
4. 多人开发时使用自己的本地分支,这是防止在代码测试完毕前直接在develop分支上对多人开发操作造成问题,一般是代码写好后一次推到develop分支上。

版本管理

在前面基础知识差不多后,接下来就是规范化的自动化的内容了。俗话说没有规矩,不成方圆,在版本管理时也是,一套成熟的管理规则可以规避很多开发混乱导致的问题。比起自己定义一套规则,使用成熟的版本管理规则显然更为高效。

约定式提交

前面有说到,每次提交解决一个问题,那么问题那么多,怎么对问题进行标准化的描述,方便后期程序进行自动化提取重要信息呢。这里介绍一下约定式提交,它的提交格式是这样的

<类型>[可选的作用域]: <描述>

[可选的正文]

[可选的脚注]

比如

fix: finish the blog

这样就是一条最基本的约定式提交了。自动化的工具就会将其归类到fix下。其余信息在其官方网站上有详细的描述。

语义化版本

为了提高版本的可读性,需要给每个版本起名字,版本号的定义也有一定的学问。起好版本号,能让人一眼看出版本号所代表的意义。语义化版本提出了一套版本号的语义规范,按照这套规范对版本号进行定义可以有效提高版本号的识别度。语义化版本提出了“主版本号.次版本号.修订号”这样的三级版本号的设置,版本号递增基本规则如下:

主版本号:当你做了不兼容的 API 修改,
次版本号:当你做了向下兼容的功能性新增,
修订号:当你做了向下兼容的问题修正。
先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。
前面版本号进位后,后面的版本号要置零。

例如“2.0.5-alpha+001”就表示主版本号为2,次版本号为0,修订号为5,先行版本号为alpha,版本编译信息为001。

版本发布工具

版本发布的自动化工具可以使用standard-version,如果每次提交都遵守约定式提交来填写信息,那么这个工具可以自动收集本次到上一次发布版本之间所有的提交信息,自动归类并计算出语义化版本号,还会自动在节点上打上版本标签,当遇到BREAKING CHANGES标签还能够自动增加次版本号,非常便捷。

工具的推荐

最后,基本的Git是使用命令行操作的,直接上手不是那么容易,但是在搞清楚基本概念后使用图形化的操作方式是很好上手的,下面推荐一些对应的工具。


知识共享许可协议
本作品由yellowko采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。

关于 “Git与项目管理” 的 2 个意见

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据