导言
本文将介绍一个被广泛使用的, 基于 Git 的项目管理工作流程 Git flow.Git flow 是 Git 的一个扩展集, 这里我们介绍当前最流行的 AVH 版本, AVH 版本以 Vincent Driessen 提出的分支模型为基础, 在已有的 Git flow 上增加了更多的功能, 同时重写了部分内置命令的实现, 从而在提供高层次的库操作同时, 对性能也有进一步的提升.
背景
从毕业之后, 以一线后台程序员的身份, 陆续几年工作到现在. 前前后后使用过 c/c++,java,python,Node.JS 和 golang 等多种语言, 与此同时, 使用的代码版本控制工具也有 TFS,SVN 和 Git. 而目前更多的, 大家使用的都是 Git 作为版本控制工具, 对于一般的项目(大中小型), 当你不知道使用哪种版本控制工具时, Git 永远都是最佳适合. 当然, Git 作为现代化的分布式版本管理工具, 使一个程序员在自己开发代码时可以在很多地方做很多事情. 然而, 当我们放大项目和团队规模, 随着在同一个项目内一起开发的人越多, 每个人的 commit 习惯不同, 在我们使用 Git 管理项目时, 会很容易出现错乱和冲突. 此时, 一个统一的, 规范的, 特定的工作流程就很必要了.
在 2010 年, Vincent Driessen 提出了一个经典的 Git 分支模型, 有兴趣的同学可以去下文阅读: Vincent Driessen's branching model. 本文介绍的 Git flow 就是以 Vincent Driessen 的分支模型, 致力于通过 Git 的分支和发布策略帮助开发者轻松地跟踪当前项目的功能开发, 紧急修复, 发布等. 考虑到阅读本文的都已经具备基本的 Git 知识, 我们直接来看看一个完整的 Git flow 分支管理体系图示:
一个完整的 Git flow 分支体系图
在网络上, 有很多关于 Git flow 的分支走向图, 但是作者觉得最清晰, 最全面的还是上面这幅. 这幅图涵盖了本文的几乎所有内容, 接下来的所有内容几乎都是契合着这张图来说明.
首先, 由上图所示, 显而易见地, 在 Git flow 版本控制管理中, 主要存在着五个分支: master,release,develop,feature 和 hotfix, 其中:
1. 长期分支
master: 主分支, 主要是用来存放稳定的, 可随时上线的版本. master 分支不允许直接进行代码 commit, 只可以接收分支的 merge request(GitLab)或者 pull request(GitHub).
develop: 主开发分支, 每次迭代都是主要在该分支上进行, 当需要开发一个个新功能时, 所有的 feature 分支都是从该分支切出去的. 而 feature 分支的功能完成后, 也都需要合并回來该分支.
2. 临时分支
release: 发布分支, 该分支上的代码将会被通过完整测试, 并将用于下一次发布. 通过单独的 release 分支进行测试, 既可以保证在从 develo 切出 release 之后可以立即在 develop 上继续开发, 从而实现开发与测试的并行, 同时也避免了 develop 分支的开发代码污染道测试版本.
feature: 功能开发分支, 主要用于在一个迭代中, 由 develop 分支切出来, 用于开分不同功能开发.
hotfix: 紧急修复分支, 主要用于修复线上 bug, 只会从 master 分支拉出, 且在修复完毕 bug 后, 需要同时合并到 master 分支和 develop 分支.
上述分支中, master 和 develop 是两个长期存在的分支, 伴随着整个项目的生存周期而存在着, 而其他分支, 将会随着每一个 Git flow 任务的开始和结束而被创建和删除.
安装 Git glow
macOS
通过 Homebrew:
- $ brew install Git-flow-avh
- Linux
在 Ubuntu 下, 通过 apt-get:
$ apt-get install Git-flow
或者, 通过源码安装:
- $ wget --no-check-certificate -q https://raw.githubusercontent.com/petervanderdoes/gitflow-avh/develop/contrib/gitflow-installer.sh && sudo bash gitflow-installer.sh install stable; rm gitflow-installer.sh
- Windows (Cygwin)
- $ wget -q -O ---no-check-certificate https://raw.githubusercontent.com/petervanderdoes/gitflow/develop/contrib/gitflow-installer.sh
- $ ./gitflow-installer.sh install state $ rm -rf gitflow gitflow-installer.sh
更过关于安装 AVH 版本的 Git flow, 可以参考这个链接: Git flow avh 版本安装指引
初始化 Git flow
$ Git flow init [-d]
当在项目的根目录执行 "git flow init" 命令时, 将会有一个交互式安装引导初始化操作. 该操作主要是在分支上配置了一些命名规则. 需要注意的是, 尽管 Git flow 允许使用自定义的名称, 但是强烈建议使用默认的命名机制, 并且一步一步地确定下去, 或者直接使用 - d 参数(-d 参数, 表示接收所有默认的配置).
- $ Git flow init -d
- Initialized empty Git repository in /data/code/src/example_repo/.Git/
- Branch name for production releases: [master]
- Branch name for "next release" development: [develop]
- How to name your supporting branch prefixes?
- Feature branches? [feature/]
- Release branches? [release/]
- Hotfix branches? [hotfix/]
在项目初始, 我们必定要将两个长期分支创建出来: master 和 develop. 接下来, 就让我们步入使用 Git flow 的主要流程中来.
开发新功能(feature)
开始一次功能开发
敏捷是当前软件开发行业的一个主要模式, 在一次迭代中, 一般都是有着多个功能等待开发完成. 在做新功能开发时, 使用一个独立的分支是版本控制中最重要的规则之一. 在多人开发同一个项目时, 每个人在迭代初始领取任务之后, 我们便可以进入到 develop 分支, 并开始一次新功能的开发:
$ Git flow feature start multiDownload
通过在 develop 分支上进行上述的操作, Git flow 会创建并到换到一个名为 feature/multiDownload 的分支(前缀 feature 可以配置是否默认添加, 建议保持加上), 这样我们就可以在新的功能分支上直接进行工作了, 对应的分支扭转图示如下:
开始一次新功能开发
完成一次功能开发
经过几晚加班后, 终于完成了一个功能的开发, 这时候, 我们需要借用 Git flow 来继续完成之前的新功能开发流程:
$ Git flow feature finish multiDownload
通过上述命令, Git flow 会帮我们完成如下一系列的操作:
将我们的代码 merge 到主 develop 分支中去.
清理操作, 删除这个 feature 分支, 并且换到 develop 分支.
上述过程对应的分支扭转图示如下:
完成一次新功能开发
当顺利的完成一个功能开发之后, 我们便可以去进行下一个功能开发, 如果当前迭代的功能全部开发完毕之后, 我们则需要去进入完整的版本测试流程.
发布新版本(release)
当一次迭代开发完成, 并充分的测试完成之后, 我们便需要准备开始一次发布操作了, 在 Git flow 中, 对于发布流程有着一套非常标准的操作:
开始一次发布流程
$ Git flow release start 1.2.0
其中 1.2.0 是我们对 release 的分支名, 通常来说, release 分支我们都使用版本号来命名. 通过上述操作, Git flow 会为我们创建并切换到一个新的分支: release/1.2.0. 而在该分支上, 我们将会进行代码编译, 并发布到生产环境 *, 对应的图示流程如下:
开始一次发布流程
* 注意: 这个地方, 作者建议在 release 分支上, 对测试已经通过的代码进行直接编译并部署到生产环境. 可能有的同学会疑问: 为什么不使用 master 分支作为代码编译的分支? 主要原因就是下文将提到的.
发现问题
当我们上线并回归测试时, 可能会立即发现了问题, 这时候还是需要在 release 分支上进行修改测试和继续发布操作. 该步骤的出现概率一般都是比较低的, 因为所有到了 release 分支的代码都是经过了大量的测试的. 但是, 诸如上生产后在回归测试的时候, 可能立刻就直接发现了一个 bug 的现象还是会存在的. 此时, 正确的操作是在当前 release 分支上直接作出修改, 提交和再发布, 等到确保再无 bug 之后, 再进入到 Git flow 的完成发布流程. 对应的分支扭转图示如下:
在 release 过程中修复问题
完成一次发布流程
当上线完毕, 并回归测试确定没有 bug 之后, 我们需要完成本次 release. 请注意, 这是一个较危险的操作:
$ Git flow release finish 1.2.0
通过这个命令, Git flow 会帮我们完成如下一系列的操作:
拉取远程仓库, 以确保目前是最新的版本.
将 release 的内容同步 merge 到 "master" 和 "develop" 两个长期分支中. 这是很重要的一个操作, 可以保证生产环境代码 (master 分支) 和主功能开发代码 (develop 分支) 是一致的.
release 提交会被标记上这个 release 的名字(也即是 1.2.0).
清理操作, 这个 release 分支会被删除, 并且切换到 develop 分支.
到这儿, 一个版本发布过程已经完成, 对应的分支扭转图示如下, 我们可以看到 release 分支的内容会被同时合并到 master 和 develop 分支:
完成一次发布流程
bug 修复(hotfix)
当我们的产品在稳定的运行了一段时间后, 可能在某天, 因为某个不常见的场景, 触发了一个严重的 bug. 这时候我们就需要走一个 bug 紧急修复的流程了.
开始一次紧急修复
在开始修复之前, 如果正在 develop 上开发新迭代的功能, 可以通过 commit 提交保存代码(如果不适合提交, 也可以通过 stash 暂存). 请记住, 所有的 hotfix 用于都是从 master 分支拉出, 因此当 Git 工作区干净之后, 我们需要切换到 master 分支, 然后开始一次紧急修复操作:
$ Git flow hotfix start authFailed
通过上述操作, Git flow 会创建并切换到一个新的分支 hotfix/authFailed, 我们将在该分支上对 bug 进行修复, 测试和上线 *, 对应的分支扭转图示如下:
开始一次紧急修复
* 注意: 与上文的 release 一样, 当 hotfix 代码修复和测试完成之后, 我们直接在 hotfix 分支上进行编译和发布. 这样操作的原因, 同样是为了避免上线回归后, 发现并没有真正的修复问题(或是代入了新的问题), 此时我们需要继续在 hotfix 分支上继续进行修改, 并在最后回归通过后, 再完成紧急修复流程.
完成一次紧急修复
当确认 bug 已经被修复, 我们需要完成本次 hotfix:
$ Git flow hotfix finish authFailed
通过上述操作, Git flow 将会进行一个非常类似于发布一个 release 版本的过程:
将代码同步 merge 到 master 分支和 develop 分支中, 同样, 通过这步操作, 可以在当前 master 分支上的 bug 被修复的同时, 保证 bug 不会再次出现在下一个 release 中(当 merge 道 develop 中时, 可能会出现冲突, 此时可能需要手动 merge 解决).
这个 hotfix 程序将被标记起来以便于参考.
清理操作, 这个 hotfix 分支会被删除, 并且切换到 develop 分支.
完成一次紧急修复
在完成紧急修复之后, 我们可以回到之前的 develop 分支继续功能开发, 请注意, 如果有进行 stash 暂存, 不要忘了 pop 出来哦.
以上就是本文关于 Git flow 的护照介绍内容, 其实所有要说的内容, 在第一张图上都可以看到踪迹. 所以在阅读完成之后, 强烈建议读者再回到本文的第一幅图, 细细品味一下一个完整的 Git flow 流程的分支管理模式.
附录
Git flow 命令一览:
Git flow 命令一览
来源: https://www.qcloud.com/developer/article/1355105