一、git-flow 的工作流程
当在团队开发中使用版本控制系统时,商定一个统一的工作流程是至关重要的。git-flow 是一个当前非常流行的工作流程。git-flow 并不是要替代 Git,它仅仅是非常聪明有效地把标准的 Git 命令用脚本组合了起来。一旦安装安装 git-flow,你将会拥有一些扩展命令。这些命令会在一个预定义的顺序下自动执行多个操作。严格来讲,你并不需要安装什么特别的东西就可以使用 git-flow 工作流程。你只需要了解,哪些工作流程是由哪些单独的任务所组成的,并且附带上正确的参数,以及在一个正确的顺序下简单执行那些对应的 Git 命令就可以了。当然,如果你使用 git-flow 脚本就会更加方便了,你就不需要把这些命令和顺序都记在脑子里。
项目中存在两个长期分支:
master 分支一般对应的是生产环境的代码,是稳定的发布版本,包含确定即将发布的代码;
develop 分支对应的是开发环境的代码,存放的都是最新的开发版。
三种短期分支:
feature branch 新功能分支,一般一个新功能对应一个分支,对于功能的拆分需要比较合理,以避免一些后面不必要的代码冲突;
hotfix branch 热修复分支,紧急修 bug 的时候用;
release branch 发布分支,发布时候用的分支,一般测试时候发现的 bug 在这个分支进行修复;
短期分支一旦完成开发,就会被合并到 develop 或 master,然后被删除。
GitFlow 的优势有如下几点:
并行开发:GitFlow可以很方便的实现并行开发。每个新功能都会建立一个新的 feature分支,从而和已经完成的功能隔离开来,而且只有在新功能完成开发的情况下,其对应的 feature分支才会合并到主开发分支上(也就是我们经常说的develop分支)。另外,如果你正在开发某个功能,同时又有一个新的功能需要开发,你只需要提交当前 feature 的代码,然后创建另外一个feature 分支并完成新功能开发。然后再切回之前的 feature 分支即可继续完成之前功能的开发。
协作开发:GitFlow 还支持多人协同开发,因为每个 feature 分支上改动的代码都只是为了让某个新的 feature 可以独立运行。同时我们也很容易知道每个人都在干啥。
发布阶段:当一个新 feature 开发完成的时候,它会被合并到 develop 分支,这个分支主要用来暂时保存那些还没有发布的内容,所以如果需要再开发新的 feature,我们只需要从 develop 分支创建新分支,即可包含所有已经完成的 feature 。
支持紧急修复:GitFlow 还包含了 hotfix 分支。这种类型的分支是从某个已经发布的 tag 上创建出来并做一个紧急的修复,而且这个紧急修复只影响这个已经发布的 tag,而不会影响到你正在开发的新 feature。
2.feature 分支都是从 develop 分支创建,完成后再合并到 develop 分支上,等待发布。
3.当需要发布时,我们从 develop 分支创建一个 release 分支然后这个 release 分支会发布到测试环境进行测试,如果发现问题就在这个分支直接进行修复。在所有问题修复之前,我们会不停的重复发布->测试->修复->重新发布→重新测试这个流程。
4.发布结束后,这个 release 分支会合并到 develop 和 master 分支,从而保证不会有代码丢失。master 分支只跟踪已经发布的代码,合并到 master 上的 commit 只能来自 release 分支和 hotfix 分支。
5.hotfix 分支的作用是紧急修复一些 Bug。它们都是从 master 分支上的某个 tag 建立,修复结束后再合并到 develop 和 master 分支上。
Git-flow 工作流定义了一个围绕项目发布的严格分支模型。其优点是清晰可控,使多人项目协作开发更加规范;缺点是相对复杂,需要同时维护两个长期分支。
二、安装 git-flow
在 linux 下安装 git-flow 很简单,直接 apt-get install git-flow 或者 yum install gitflow 就行,而在 windows 下安装比较麻烦,首先需要安装 git ,然后再安装 git-flow。
windows 安装 git-flow:
安装 git-flow (其中 “C:\Program Files\Git” 是git 的安装目录,根据实际情况修改):
git clone --recursive git://github.com/nvie/gitflow.git
cd gitflow/contrib
./msysgit-install.cmd “C:\Program Files\Git”
验证安装:
git flow version
1.12.3 (AVH Edition)
三、使用 git-flow
How to name your supporting branch prefixes?
Feature branches? [feature/]
Bugfix branches? [bugfix/]
Release branches? [release/]
Hotfix branches? [hotfix/]
Support branches? [support/]
Version tag prefix? []
Hooks and filters directory? [F:/aaa/dd/cpp/.git/hooks]
当在项目的根目录执行 “git flow init” 命令时(它是否已经包括了一个 Git 仓库并不重要),一个交互式安装助手将引导您完成这个初始化操作。
2.新功能开发
$ git flow feature start const-ref-pointer
Switched to a new branch ‘feature/const-ref-pointer’
Summary of actions:
Now, start committing on your feature. When done, use:
git flow feature finish const-ref-pointer
此时会多出一个分支 feature/const-ref-pointer ,开发工作都会在在该分支进行
$ git branch
develop
功能开发完成后,结束当前阶段的工作
$ git flow feature finish const-ref-pointer
Switched to branch ‘develop’
Updating 4a18517…057aae6
Fast-forward
ref1.cpp | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 ref1.cpp
Deleted branch feature/const-ref-pointer (was 057aae6).
Summary of actions:
$ git branch
$ git flow release start v0.1
Switched to a new branch ‘release/v0.1’
Summary of actions:
Follow-up actions:
git flow release finish ‘v0.1’
现在会多出来一个release 分支 release/v0.1:
$ git branch
develop
master
有了一个 release 分支,再完成针对 release 版本号的最后准备工作(如果项目里的某些文件需要记录版本号),并且进行最后的编辑。然后完成 release:
$ git flow release finish v0.1
Switched to branch ‘master’
Merge made by the ‘recursive’ strategy.
ref1.cpp | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 ref1.cpp
Already on ‘master’
Switched to branch ‘develop’
Already up to date!
Merge made by the ‘recursive’ strategy.
Deleted branch release/v0.1 (was 057aae6).
Summary of actions:
$ git tag
v0.1
这个命令会完成如下一系列的操作:
首先,git-flow 会拉取远程仓库,以确保目前是最新的版本,也就是说如果远程仓库已经被其它人修改了,我们还需要合并进来解决冲突。
然后,release 的内容会被合并到 “master” 和 “develop” 两个分支中去,这样不仅产品代码为最新的版本,而且新的功能分支也将基于最新代码。
为便于识别和做历史参考,release 提交会被标记上这个 release 的名字(在我们的例子里是 “v0.1”)。
清理操作,版本分支会被删除,并且回到 “develop”。
4.hot fix
一般在发布版本之前发现的bug 都会直接在feature、bugfix或者develop 分支上进行修改,然后提交,而在发布之后,如果发现了问题,可以通过 hotfix branch 进行修复。比如在release 几个小时或几天之后,发现一些小问题,可以创建 hotfixes:
$ git flow hotfix start missing-compiler-file
Switched to a new branch ‘hotfix/missing-compiler-file’
Summary of actions:
Follow-up actions:
git flow hotfix finish ‘missing-compiler-file’
这个命令会创建一个名为 hotfix/missing-compiler-file 的分支,我们要在这个分支上修改发现的问题,最后完成 hotfix:
$ git flow hotfix finish missing-compiler-file
Switched to branch ‘develop’
Merge made by the ‘recursive’ strategy.
compiler_instruction.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 compiler_instruction.md
Deleted branch hotfix/missing-compiler-file (was b482eb8).
Summary of actions:
查看tag 或多出来一个 missing-compiler-file:
$ git tag
missing-compiler-file
v0.1
这个过程非常类似于发布一个 release 版本:
完成的改动会被合并到 “master” 中,同样也会合并到 “develop” 分支中,这样就可以确保这个错误不会再次出现在下一个 release 中。
这个 hotfix 程序将被标记起来以便于参考。
这个 hotfix 分支将被删除,然后切换到 “develop” 分支上去。
5.同步到远程仓库
release finish只是完成了本地代码的一系列操作,还需要同步到远程仓库。
git push origin --all
git push origin --tags
四、注意事项
gitflow 在进行merge 的时候,默认情况下它会检查本次merge有多少次commit记录,如果仅有一条采用 fast-forward 模式,如果超过一条则采用no-fast-forward模式,no-fast-forward模式下会多生成一条merge的commit记录。这样做的好处是当只有一条提交记录时如果生成一条merge记录实际上会复杂化代码记录的管理;当有多条commit记录时生成的一个merge记录,可以方便的进行代码回退和记录检查。
如果 merge时发生冲突,不会终止流程,只是不会将本地的release分支删除,当前已经处于develop分支,待解决完冲突后需再次执行finish指令。
需要注意的是,如果本地还有未finish的release分支,将不允许使用start指令开启新的release分支,这一点是对并行发布的一个限制。
五、其他代码工作流
与Gitflow相似的代码管理工作流还有,Github flow和Gitlab flow。
Github flow是简化版的Gitflow,它使用master和feature来管理代码,它只有一个长期分支,就是master。Gitlab flow更关注代码的持续集成,一个版本需要创建测试环境、预览环境、生产环境的分支,最终汇总到stable branch用于发布。