GitFlow工作流规范
文章目录
工作流规范
版本规范
前端项目使用语义化版本进行发布:
版本格式:主版本号.次版本号.修订号,版本号递增规则如下:
- 主版本号:当你做了不兼容的 API 修改,
- 次版本号:当你做了向下兼容的功能性新增,
- 修订号:当你做了向下兼容的问题修正。
先行版本号及版本编译元数据可以加到“主版本号.次版本号.修订号”的后面,作为延伸。
常见工作流
Git 分支模型
master分支
master分支表示一个稳定的发布版本. 对应GZB的大版本.
- 场景: 前端应用会跟随工作宝版本迭代, 在dev分支测试稳定后, 会合并到master分支, 并使用tag标记应用版本和对应的工作宝版本
- tag规范:
v{APP_version}@{GZB_version}
, 例如v0.1.0@GZB_6.6 - 人员: 由项目负责人进行审核合并, 普通开发者没有权限
dev分支
开发者主要工作的分支, 最新的特性或bug修复都会提交到这个分支. 开发者如果在该分支进行了提交,在push到远程之前应该先pull一下, 并尽量使用rebase模式,保证分支的简洁
- 命名规范: dev
- tag规范: 在dev分支中也可能会经历发布过程, 例如bug修复版本. 这里同样使用tag来标记这些发布. 例如v0.1.1
- 提交规范:如果实在开发分支上进行开发,在推送到远程之前,应该使用
git rebase
形式更新本地分支。
feature分支
涉及多人协作或者大功能的开发, 应该从dev分支checkout出独立的feature分支, 避免干扰dev分支
场景:
- 涉及多人协作: 团队多个成员在同一个项目下负责开发不同的功能, 这时候每个成员在自己的feature分支独立开发
- 大功能开发: 大功能开发跨越周期比较长, 需要多次迭代才会稳定. 这时候应该在独立的分支上开发. 方便跟踪历史记录, 也免于干扰dev分支的迭代和发布
命名规范
- feature/name: name是功能名称
- feature/GZB_version: 这也是团队常见的模式, 当无法使用一个功能名称来描述时, 可以使用GZB版本号作为’功能’
合并时机
- 当feature分支迭代稳定, 并通过测试后, 合并到dev分支. 合并到dev后, feature分支的生命周期就结束了. 后续bug修复和功能优化直接在dev开发
- 当多个feature分支需要合并对外发布临时版本时. 合并到preview分支 . ⚠️这种情况不应该合并到dev分支, 因为feature分支可能还不稳定或未完成. 比如为了联调某些功能.
合并方式
- 不要使用fast-forward. 这样可以在分支图上查看到分支历史
preview分支
临时的预览分支, preview分支用于临时合并feature分支, 这其中可能会修复某些bug或者冲突. 可以选择性地将这些提交cherrypick回feature分支. 当预览结束后就可以销毁preview分支
hotfix
主要负责管理生产环境下出现的紧急修复的代码。从主干分支分出,修理完毕并测试上线后,并回主干分支。并回后,视情况可以删除该分支。
release分支
release分支有两种使用策略,第一种遵循gitFlow
流程, 第二种是目前后端团队使用的策略,为了配合后端工作,我们主要使用第二种
git flow 风格的release分支
当前前端应用的稳定版本和GZB版本绑定. release分支不一定存在, 一般情况下, 只会在前端版本稳定后, 将其合并到master, 并创建tag标记. 而只有需要为指定的正式版本修复bug时才会创建release分支
版本规范
- 场景: 需要为某个正式版本修复bug(hotFix)时, 从master的对应tag中checkout release分支
- 命名规范:
release/{GZB_version}
外部人员只会关注GZB版本 - 如何修复
- 如果对应bug可以在dev分支直接被修复, 可以先提交到dev分支(或者已经修复了), 然后再cherrypick到release分支
- 如果bug在新版本无法复现. 比如新版本升级了依赖. 那么在release分支直接修复即可
自定义风格release分支
版本规范
当要发布一个工作宝对应的版本时(或者一开始开发时)从dev分支checkout出一个开发分支,后续需要对外发布时,将dev分支合并到release分支, 并打上版本tag. 后面会介绍到后端开发和自动交付机制这种分支模式。
这一种使用策略. gzb后端在使用, 为了配合后端工作, 我们也推荐使用这种方式
何时创建:
- 开启GZB新版本开发任务时(推荐)
- 向外发布第一个版本时
何时合并:后面dev有版本发布都要合并到release分支,直到开启另一条release分支
好处
- 对发布内容进行筛选
- 专门用于发布, 开发者容易过滤变更的内容
提交信息规范
一个好的提交信息, 会帮助你提高项目的整体质量.
why
- 格式统一的提交信息可以帮助自动化生成changelog
- 版本库不只是存放代码的仓库, 也记录项目的开发记录. 这些记录应该可以帮助后来者快速地学习和回顾代码. 也应该方便其他协作者review你的代码
原则: 半年后, 你能看懂你的commit做了什么东西
方式: 使用git commit(打开编辑器)而不是git commit -m
必要信息
为什么进行这次提交?
- 提交改变了什么, 让其他reviewer更容易审核代码和忽略无关的改变
如何解决的问题?
- 问题是什么导致的?
- 简短说明使用什么方式, 策略, 修复了问题.
变化可能影响哪些地方
- 说明变动功能的细节。 一个提交不应该做超过2个功能的变动
格式
社区上比较流行的提交信息规范是Angular的提交信息规范
我们采用angular的提交规范, 在这个规范的基础上支持(可选)emoji
进行修饰
1 2 3 4 5 |
<type>(<scope>): <subject> <body> <footer> |
header
如果提交时feature或者fix(已发布的版本), 这些提交信息应该出现在CHANGELOG
type: 说明commit的类别. 可以配合emoji使用, 让阅读者更快地区分提交的类型,允许以下类型:
- ✨feature或feat: 引入新功能
- 🐛fix: 修复了bug
- 📝docs: 文档
- 🎨style: 优化项目结构或者代码格式
- ♻️refactor: 代码重构. 代码重构不涉及新功能和bug修复. 不应该影响原有功能, 包括对外暴露的接口
- ✅test: 增加测试
- ⏫chore: 构建过程, 辅助工具升级. 如升级依赖, 升级构建工具
- ⚡️perf: 性能优化
⏪ revert: revert之前的commit
- git revert 命令用于撤销之前的一个提交, 并在为这个撤销操作生成一个提交
🎉 build或release: 构建或发布版本
🔒 safe: 修复安全问题
scope: 可选. 说明提交影响的范围. 例如样式, 后端接口, 逻辑层等等
Subject: 提交目的的简短描述, 动词开头, 不超过80个字符. 不要为了提交而提交
body
可选. 对本次提交的详细描述. 如果变动很简单, 可以省略
footer
可选. 只用于说明不兼容变动(break change)和关闭 Issue(如果使用使用gitlab或github管理bug的话)
模板和示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 50-character subject line # # 72-character wrapped longer description. This should answer: # # * Why was this change necessary? # * How does it address the problem? # * Are there any side effects? # # Include a link to the ticket, if any. feat(forms):使表单状态使用更严格的类型。( #42952 ) 具体来说:将用于表单状态的类型从字符串缩小到可能状态的联合。将 API 方法从 any 更改为使用新类型。 这是一个突破性的变化。然而,正如 PR 中所讨论的,破损似乎很少,google3 已经准备好解决这个问题。 背景:我们在键入表单的设计工作过程中发现了这些任何类型。它们可以通过将它们搭载在新类型的表单泛型之上以不间断的方式进行修复,但如果可能的话,单独修复它们会更清晰。 突破性变化: 引入了一种名为“FormControlStatus”的新类型,它是表单控件所有可能状态字符串的联合。`AbstractControl.status` 已经从`string` 缩小到`FormControlStatus`,`statusChanges` 已经从`Observable<any>` 缩小到`Observable<FormControlStatus>`。大多数应用程序应该无缝地使用新类型。此更改导致的任何损坏都可能是由于以下两个问题之一造成的:(1) 应用程序正在将 `AbstractControl.status` 与无效状态的字符串进行比较;或者,(2) 应用程序正在使用 `statusChanges` 事件,就好像它们不是字符串一样。 |
BUG 处理规则
对于测试,目前会经历两个阶段
- 冒烟测试:在对测试正式发版之前会要求对代码进行自测,及冒烟测试。
- 正式测试阶段:正式测试阶段测试人员会在RDMS进行bug提交和管理,对BUG的处理规则如下:
- [解决待关闭]: 修改了程序代码, 问题解决;
- [不做处理]: 没有修改程序代码, 是由于其他原因(需求变更等), 而解决的问题;
- [退回]: 无规律或只出现一次的BUG, 研发没找到原因, 加上必要排查日志后, 可退回给测试; 复现后重新打开
- [正在处理]: 已大致定位原因, 需要较多时间处理的BUG, 可置为”正在处理”
如何处理定制化需求
痛点
- 对于定制化需求, 并不会引入到正规的代码流中, 一般情况下会checkout出一个分支, 来专门做这里定制化需求, 然后单独发版. 使用分支模式的缺点有:
- 更新问题
- 每次正规代码更新都要合并到该分支. 当分支较多时分支图就会比较混乱
- 正规代码合并是必然会带来风险的, 比如项目结构变动, 依赖库变动. 都可能导致定制化的代码失效
- 更新问题
- 对于定制化需求, 并不会引入到正规的代码流中, 一般情况下会checkout出一个分支, 来专门做这里定制化需求, 然后单独发版. 使用分支模式的缺点有:
解决办法
减少代码耦合
- 尽量将定制化需求模块化, 最小化和正规代码之间的接触面. 这是解决该问题最根本的方式.
- 检验方式是结构变化时, 没有或很少适配代码
- 尽量将定制化需求模块化, 最小化和正规代码之间的接触面. 这是解决该问题最根本的方式.
考虑通过代码层面区分
- 例如通过权限系统来配置. 通过后端接口动态配置
优先使用fork模式
- 有些场景确实无法通过代码层面解决, 比如ios应用定制启动图, icon, 应用名称, 外观等等. 这种方式优先使用fork模式, fork模式和分支模式没本质区别, 但是至少可以避免干扰正规开发流程
通用的项目组织规范
一个典型的项目组织规范如下:
README.md: 项目说明, 这个是最重要。你必须在这里提供关于项目的关键信息或者相关信息的入口. 一般包含下列信息:
- 简要描述、项目主要特性
- 运行环境/依赖、安装和构建、测试指南
- 简单示例代码
- 文档或文档入口, 其他版本或相关资源入口
- 联系方式、讨论群
- 许可、贡献/开发指南
CHANGELOG.md: 放置每个版本的变动内容, 通常要描述每个版本变更的内容。方便使用者确定应该使用哪个版本. 关于CHANGELOG的规范可以参考keep a changelog
package.json: 前端项目必须. 描述当前的版本、可用的命令、包名、依赖、环境约束、项目配置等信息.
.gitignore: 忽略不必要的文件,避免将自动生成的文件提交到版本库
.gitattributes: git配置,有一些跨平台差异的行为可能需要在这里配置一下,如换行规则
docs/: 项目的细化文档, 可选.
examples/: 项目的示例代码,可选.
build: 项目工具类脚本放置在这里,非必须。如果使用统一构建工具,则没有这个目录
dist/: 项目构建结果输出目录
src/: 源代码目录
tests/: 单元测试目录. 按照Jest规范,
__tests__
目录通常和被测试的模块在同一个父目录下, 例如:1 2 3 4 5 6
/src __tests__/ index.ts a.ts index.ts a.ts
tests: 全局的测试目录,通常放应用的集成测试或E2E测试等用例
.env*: 项目中我们通常会使用
环境变量
来影响应用在不同运行环境下的行为. 可以通过dotEnv来从文件中读取环境变量. 通常有三个文件:.env
通用的环境变量.env.development
开发环境的环境变量.env.production
生成环境的环境变量
基本上这些文件的变动的频率很少,团队成员应该不要随意变动,以免影响其他成员。所以通常会使用.env.*.local
文件来覆盖上述的配置, 另外会设置版本库来忽略*.local
文件.
对于开源项目通常还包括这些目录:
- LICENSE: 说明项目许可
- .github
- 开源贡献规范和指南
- CONTRIBUTING: 贡献指南, 这里一般会说明贡献的规范、以及项目的基本组织、架构等信息
- CODE_OF_CONDUCT: 行为准则
- COMMIT_CONVENTION: 提交信息规范,上文已经提及
- ISSUE_TEMPLATE: Issue的模板,github可以自动识别这个模板
- PULL_REQUEST_TEMPLATE: PR模板