功能分支工作流

上面是我们之前用SVN集中式的思想来才使用Git,但这没有用到Git强大的分支功能,在开发过程中通过添加分支,来促进开发者彼此之间的协作,使得他们之间专注自己的功能而不会去打扰到主代码库,另外它还保证了master分支永远不会包含损坏的代码,给我们后面做持续集成带来了很大好处。

这也使得我们使用Pull Request(GitLab中称为Merge Request)成为可能,它用来启动一个分支的讨论,给其他开发者在此功能加入主项目之前参与决策的机会,比如你在开发功能完成一半,卡了,可以发起一个Pull Request 向同事寻求建议。重点是,Pull Request 使得你的团队在评论其他人的工作时变得非常简单。

功能分支工作流同样使用远程仓库,master分支同样代表官方的项目历史,但是与其直接提交到本地master分支不同的是,开发者每次在进行新的工作时都会创建一个功能分支,该分支应该包含描述性的名称,比如:feature-login或者bug-#1011(开源项目中习惯用issue-#1011),后者代表BUG的ID号。然后开发者就可以和之前一样,用标准的流程在功能分支上进行编辑、暂存、提交。

Git分支命名规范:

分支

命名

说明

主分支

master

主分支,所有提供给用户使用的正式版本,都在这个主分支上发布

开发分支

develop

开发分支,永远是功能最新最全的分支

功能分支

feature-*

新功能分支,某个功能点正在开发阶段

发布版本

release-*

发布定期要上线的功能

修复分支

bug-*

修复线上代码的 bug

同样,每一个功能分支也可以被推送到远程仓库,便于开发者本地的备份。然后发布一个Pull Request,请求将他们的修改并入master主项目,这样就给了其他开发者,尤其是项目负责人在修改并入主项目库之前进行代码审查(code review)的机会。

代码审查完毕,Pull Request被接受,后面的就是一样的,首先同步你本地的master分支,然后将功能分支并入master,最后推送到远程仓库。

接下来举例来说明一下这个工作流是如何工作的:

1. 初始化中央仓库

首先是我们的项目负责人在服务器上创建中央仓库,如果这是一个新项目,你可以初始化一个空的仓库,不然,你需要导入一个已经存在的Git或者SVN项目。

中央仓库应该永远是裸仓库(没有工作目录),命令如下:

ssh user@host
git init --bare /path/to/repo.git

注意这里使用的SSH用户名userhost服务器域名或者IP地址、储存仓库的地址/path/to/repo.git都是有效的。

针对GitHub或者GitLab用户还可以使用图形界面来代替上面的操作。

2. 所有人将仓库克隆到本地

接下来,每个开发者在本地clone一份完整项目的副本:

git clone ssh://user@host/path/to/repo.git

当克隆完仓库时,Git自动添加一个名为origin的远程连接,指向父仓库,以便你以后和这个仓库交换数据。

前面两步和集中式工作流是一样的

3. 小张开始做新功能A

在小张开发功能A之前,他需要新建一个独立的功能分支A,命令如下:

git checkout -b feature-A master

这是一个基于master,名为feature-A的分支,-b参数表示该Git分支不存在时创建它。在这个分支上,小张和我们前面说的Git标准流程一样,编辑、暂存、提交。

git status # 查看当前分支状态
git add <commit-file> # 暂存某个文件
# git add . # 暂存当前目录下所有文件
git commit -m "提交说明"

4. 小张做第一次提交

git push -u origin feature-A

这个命令将feature-A推送到中央仓库origin中,-u标记它将添加为远程跟踪的分支。在设置完跟踪的分支只有,小张就可以调用不带任何参数的 git push来推送他提交的功能。

5. 小张发起Pull Request

当小张完成功能后,在并入master之前,他需要发起一个Pull Request,让其他团队成员知道他所做的工作,但首先,他应该保证中央仓库包含了他最新的提交:

git push

然后,登录他的Git的界面(这里一般指Gitlab和Github这类平台),发起一个Pull Request,请求将feature-A合并进master,团队成员会收到自动的通知,同时,你也可以和协作者在提交正下方评论,方便讨论特定的修改。

6. 小王收到了Pull Request

小王是项目负责人,他收到了Pull Request,并且查看了feature-A,他决定在并入官方项目之前做一些修改,通过Pull Request和小张进行沟通。

7. 小张修改内容

为了做这些修改,小张重复之前的标准流程,编辑、暂存、提交、将修改推送到中央仓库,他的所有活动都会显示在Pull Request中,小王也可以根据其提交进行评论。

同时,小王也可以将feature-A分支pull到自己本地,继续工作,后续的任何提交都会显示在Pull Request中。

8. 小王同意小张更改并入master

git checkout master
git pull
git pull origin feature-A
git push

首先,不管谁在执行合并操作,都要保证master分支是最新的,然后运行git pull origin feature-A合并中央仓库的feature-A副本,当然也可以使用git merge feature-A,之前的命令保证你拉取下来的一定是最新的功能分支版本。最后更新的master需要被推送会origin

这里的merge导致了一个合并提交,但是如果你想得到一个线性的提交历史,你也可以选择rebase来产生一个快速向前的合并。

一些平台会自动接受Pull Request流程,你只需点击一下「Merge Pull Request」的流程,合并完之后自动的关闭Pull Request。

9. 小李开发功能B

小李也可以和小张一样的方式来开发他自己的功能B,通过这样的将功能用不同的分支隔离开来,每个人都可以独立的工作,也可以很容易的和别人共享自己的修改。