Appearance
基于功能(feature)分支的工作流
上面是我们之前用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用户名user
和host
服务器域名或者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,通过这样的将功能用不同的分支隔离开来,每个人都可以独立的工作,也可以很容易的和别人共享自己的修改。