Go Engineering - Specification - Commit
规范化的优势
优势:Commit Message 可读性更好 + 自动化
- 清晰地知道每个 Commit 的变更内容
- 基于 Commit Message 进行过滤查找:
git log --oneline --grep "^feat|^fix|^perf"
- 基于 Commit Message 生成 Change Log
- 基于 Commit Message 触发 CICD 流程
- 确定语义化版本的版本号
- fix 类型映射为 PATCH 版本
- feat 类型映射为 MINOR 版本
- 带有 BREAKING CHANGE 的 Commit 映射为 MAJOR 版本
Angular 规范
- Angular 格式清晰,使用最为广泛;Angular 规范是一种语义化的提交规范
- Commit Message 是语义化的
- Commit Message 都会被归为一个有意义的类型,用来说明本次 Commit 的类型
- Commit Message 是规范化的
- Commit Message 遵循预先定义好的规范,可以被开发者和工具识别
样例
规范
Commit Message 组成部分:Header(必须)、Body 和 Footer
1 | <type>[optional scope]: <subject> |
Header
只有一行,对 Commit 的高度概括
type
Commit 的类型
- Development
- 项目管理类的变更,不会影响最终用户和生产环境的代码,如 CICD 流程、构建方式等修改,可免测发布
- Production
- 会影响最终用户和生产环境的代码,在提交前需做好充分测试
scope
Commit 的影响范围(名词),不同的项目会有不同的 scope,scope 不适合设置太具体的值(预先规划 + 文档化)
Could be anything specifying place of the commit change (users, db, poll)
subject
Commit 的简短描述:小写的动词开头,使用现在时,结尾不能加英文句号
Concise description of the changes. Imperative, lower case and no final dot
Body
可以分成多行,格式相对自由,对 Commit 的详细描述
以动词开头,使用现在时,必须包含修改的动机 + 相对于上一版本的改动点
Motivation for the change and contrast this with previous behavior
Footer
用来说明本次 Commit 导致的后果:不兼容的改动、关闭的 issue 列表
Information about Breaking Changes and reference issues that this commit closes
1 | BREAKING CHANGE: <breaking change summary> |
不兼容的改动
在 Footer 部分,以 BREAKING CHANGE 开头,后面跟上不兼容改动的摘要,Footer 其他部分说明变动的描述、变动理由和迁移方法
1 | BREAKING CHANGE: isolate scope bindings definition has changed and |
关闭的 issue 列表
关闭的 Bug 需要在 Footer 部分新建一行,并以 Closes 开头列出
1 | Closes #123, #432, #886 |
Revert Commit
如果当前 Commit 还原了先前的 Commit,应该以 revert: 开头,后跟还原的 Commit 的 Header
Body 必须写成:This reverts commit <hash>
,hash 为要还原的 Commit 的 SHA 值
1 | revert: feat(iam-apiserver): add 'Host' option |
Commit
提交命令
为了更好地遵循 Angular 规范,直接使用
git commit
或者 **git commit -a
**,不要使用git commit -m
提交频率
下班前固定提交一次,并确保本地未提交的代码延期不超过 1 天
重写历史
git rebase
合并提交:新的 Commit 合并到主干时,只保留 2~3 个 Commit
1 | # git checkout -b feature/user |
1 | # git log --oneline |
git rebase -i 9db04ee -> 需要合并的 Commit 中最旧的 Commit 的父 Commit
git log -> 新的 Commit
git reset
如果有太多 Commit 需要合并,可以先撤销过去的 Commit,再新建一个 Commit
不推荐,比较粗暴,需要整理一遍之前提交的 Commit Message
1 | # git reset HEAD~3 |
修改 Message
git commit --amend
–> 修改最近一次 Commit 的 Messagegit rebase -i
–> 修改某次 Commit 的 Message
git commit --amend
1 | # git log --oneline |
1 | # git commit --amend |
生成新的 Commit
1 | # git log --oneline |
git rebase -i
git rebase -i <father commit ID>
在实际开发中,使用频率比较高
1 | # git log --oneline |
1 | # git rebase -i 5e6b61b |
1 | # git log --oneline |
注意
- Commit Message 是 Commit 数据结构中的一个属性,如果 Commit Message 变更,则 Commit Id 一定会发生变化
git commit --amend
:只会变更最近一次的 Commit Idgit rebase -i
:会变更父 Commit Id 之后所有提交的 Commit Id
- 如果当前分支有未 Commit 的代码,先执行
git stash
将工作状态进行暂存,后续再通过git stash pop
恢复之前的工作状态
自动化
Tool | Desc |
---|---|
commitizen-go | Command line utility to standardize git commit messages, golang version. |
commit-msg | A Git hook automatically invoked by git commit commit-msg 调用 go-gitlint 来进行检查 |
go-gitlint | Go lint your commit messages! 检查历史提交的 Commit Message 是否符合 Angular 规范,可以集成到 CI 中 |
gsemver | gsemver is a command line tool developed in Go (Golang) that uses git commit convention to automate the generation of your next version compliant with semver 2.0.0 spec. |
git-chglog | CHANGELOG generator implemented in Go (Golang). Anytime, anywhere, Write your CHANGELOG. |