扫码订阅《 》或入驻星球,即可阅读文章!

GOLANG ROADMAP

阅读模式

  • 沉浸
  • 自动
  • 日常
首页
Go友会
  • 城市
  • 校园
Go学院
  • Go小课
  • Go小考
  • Go实战
  • 精品课
Go求职
  • 求职辅导🔥
  • Offer收割社群
  • 企业题库
  • 面试宝典
Go宝典
  • 在线宝典
  • B站精选
  • 推荐图书
  • 每日博文
Go仓库
实验区
  • Go周边
  • Go下载
  • Go月刊
消息
更多
  • 用户中心

    • 我的信息
    • 推广返利
  • 玩转星球

    • 星球介绍
    • 角色体系
    • 星主权益
  • 支持与服务

    • 联系星主
    • 成长记录
    • 常见问题
    • 吐槽专区
  • 合作交流

    • 渠道合作
    • 课程入驻
    • 友情链接
author-avatar

GOLANG ROADMAP


首页
Go友会
  • 城市
  • 校园
Go学院
  • Go小课
  • Go小考
  • Go实战
  • 精品课
Go求职
  • 求职辅导🔥
  • Offer收割社群
  • 企业题库
  • 面试宝典
Go宝典
  • 在线宝典
  • B站精选
  • 推荐图书
  • 每日博文
Go仓库
实验区
  • Go周边
  • Go下载
  • Go月刊
消息
更多
  • 用户中心

    • 我的信息
    • 推广返利
  • 玩转星球

    • 星球介绍
    • 角色体系
    • 星主权益
  • 支持与服务

    • 联系星主
    • 成长记录
    • 常见问题
    • 吐槽专区
  • 合作交流

    • 渠道合作
    • 课程入驻
    • 友情链接
  • Go工程化规范设计

    • 前言
    • 开源规范
    • 文档规范
    • 版本规范
    • Git规范
    • 目录结构
    • 编码规范
    • 代码测试
    • 性能分析
    • API 设计
    • 项目管理
    • 研发流程
    • 参考资料
  • Go工程化标准实践

    • 前言
    • 项目结构
    • API 设计
    • 配置管理
    • 模块管理
    • 测试
    • 参考资料

扫码订阅《 》或入驻星球,即可阅读文章!

Git规范


Kyle

# Commit 规范

常见的开源社区 commit message 规范:

比如 Angular 规范:

  • 语义化:commit message 被归为有意义的类型用来说明本次 commit 的类型。
  • 规范化:commit message 遵循预先定义好的规范,比如格式固定、都属于某个类型,可被开发者和工具识别。

基本格式:

<type>[optional scope]: <description>
// 空行
[optional body]
// 空行
[optional footer(s)]
1
2
3
4
5

建议使用 git commit 时不要使用 -m 选项,而 -a 进入交互界面编辑 commit message。

# Header

只有一行,包括:type(必选)、scope(可选)和 subject(必选)。

type 分为:

  • Development:一般是项目管理类的变更,不会影响最终用户和生产环境的代码,比如 CI 流程、构建方式等的修改。通常可以免测发布。
  • Production:会影响最终的用户和生产环境的代码。一定要慎重并在提交前做好充分的测试。

scope 说明 commit 影响范围,必须是名词,因项目而异。

  • 初期可设置粒度较大的 scope(如按组件名或功能设置),后续项目有变动或有新功能时可添加新的 scope。
  • 不适合设置太具体的值。会导致项目有太多的 scope 难以维护,开发者也难以确定 commit 所属的 scope 导致错放,反而失去分类的意义。

subject 是 commit 的简短描述,明确指出 commit 执行的操作,以动词开头(小写)、使用现在时,不加句号。

# Body

可分成多行,格式较自由。以动词开头、使用现在时。

必须包括修改的动机、跟上一版本相比的改动点。

The body is mandatory for all commits except for those of scope "docs". When the body is required it must be at least 20 characters long.
1

# Footer

根据需要选择,一般格式:

BREAKING CHANGE: <breaking change summary>
// 空行
<breaking change description + migration instructions>
// 空行
// 空行
Fixes #<issue number>
1
2
3
4
5
6

可说明本次 commit 导致的后果。

不兼容的改动:如当前代码跟上一个版本不兼容,需要在 Footer 部分以 BREAKING CHANG: 开头,跟上不兼容改动的摘要。其他部分需要说明变动的描述、变动的理由和迁移方法:

BREAKING CHANGE: isolate scope bindings definition has changed and
    the inject option for the directive controller injection was removed.

    To migrate the code follow the example below:

    Before:

    scope: {
      myAttr: 'attribute',
    }

    After:

    scope: {
      myAttr: '@',
    }
    
    The removed `inject` wasn't generaly useful for directives so there should be no code using it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

关闭的 Issue 列表:关闭的 Bug 需要在 Footer 部分新建一行,并以 Closes 开头列出,比如:Closes #123。如果关闭多个 Issue,可以列出:Closes #123, #432, #886。

Change pause version value to a constant for image
   
   Closes #1137
1
2
3

# Revert Commit

如果当前 commit 还原了先前的 commit,则应以 revert: 开头,后跟还原的 commit 的 Header。而且,在 Body 中必须写成 This reverts commit ,其中 hash 是要还原的 commit 的 SHA 标识。

revert: feat(iam-apiserver): add 'Host' option

This reverts commit 079360c7cfc830ea8a6e13f4c8b8114febc9b48a.
1
2
3

# 管理 Commit

在对项目进行修改,通过测试(修复 bug、完成 feature)后立即 commit;或约定一个提交的周期,减少本地代码丢失造成的代码丢失量。要避免 commit 太多,可在合并代码或提交 PR 时使用 git rebase -i 合并之前所有提交:建议把新的 commit 合并到主干时只保留 2~3 个 commit 记录。

使用 git rebase -i commitId 进入交互界面,可列出该 commitId 之后的所有 commit。其支持的操作(默认是 pick):

其中 squash 和 fixup 可用于合并 commit(注意是处理 commitId 和 HEAD 之间的 commit,开区间)。比如临时切换到 feature 分支进行开发:

git log --oneline
# 7157e9e docs(docs): append test line 'update3' to README.md
# 5a26aa2 docs(docs): append test line 'update2' to README.md
# 55892fa docs(docs): append test line 'update1' to README.md
# 89651d4 docs(doc): add README.md

# ========== feature/user 开发... ==========

git log --oneline
# 4ee51d6 docs(user): update user/README.md
# 176ba5d docs(user): update user/README.md
# 5e829f8 docs(user): add README.md for user
# f40929f feat(user): add delete user function
# fc70a21 feat(user): add create user function

# 以上是切换到 feature/user 分支进行开发后提交的 commit。

# 7157e9e docs(docs): append test line 'update3' to README.md
# 5a26aa2 docs(docs): append test line 'update2' to README.md
# 55892fa docs(docs): append test line 'update1' to README.md
# 89651d4 docs(doc): add README.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

在 feature 分支上的 5 个 commit 要在合并到 master 分支前进行精简,可选取切换 feature 分支前的最后一个 commit 进行 rebase(比如 squash 操作)。最终 pick 前的四个 commit 都会被删除。

git rebase -i 7157e9e
# pick 4ee51d6 docs(user): update user/README.md
# s 176ba5d docs(user): update user/README.md
# s 5e829f8 docs(user): add README.md for user
# s f40929f feat(user): add delete user function
# s fc70a21 feat(user): add create user function
# Rebase 7157e9e..4ee51d6 onto 7157e9e (5 commands(s))

git log --oneline
# d6b17e0 feat(user): add user module with all function implements
# 7157e9e docs(docs): append test line 'update3' to README.md
# 5a26aa2 docs(docs): append test line 'update2' to README.md
# 55892fa docs(docs): append test line 'update1' to README.md
# 89651d4 docs(doc): add README.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14

除此之外,如果有太多 commit 需要合并,可以先撤销过去的 commit,再创建一个新的(需要重新整理 commit message):

git reset HEAD~3
git add .
git commit -am "feat(user): add user resource"
1
2
3

# 修改 Commit

修改最近提交的 commit:

git log --oneline
git commit --amend
1
2

修改某次 commit:

git rebase -i previousCommitId
1

第二种会导致父 commit 之后所有 commit 的 commitId。可能需要 git stash 将当前分支工作状态暂存,修改完成后再进行 git stash pop 恢复。

# 分支管理

# 集中式

所有开发者直接在 master 分支上工作。

# 功能分支

在开发新功能时基于 master 分支新建一个功能分支,在功能分支上进行开发,完成之后合并到 master 分支。

# 新建功能分支
git checkout -b feature/rate-limiting

# 开发工作提交到功能分支
git add limit.go
git commit -m "add rate limiting"

# 将本地功能分支代码 push 到远程仓库
git push origin feature/rate-limiting

# 在远程仓库上创建 PR,CR 后 Merge 即可
1
2
3
4
5
6
7
8
9
10
11

Merge PR 推荐使用 Create a merge commit 模式,即 git merge --no-ff,feature 分支上所有的 commit 都会加到 master 分支上,并且会生成一个 merge commit,避免丢失历史记录。

# Git Flow(推荐)

常用于非开源项目。共有以下类型的分支:

示例场景:

  • 当前版本为:0.9.0。
  • 需要新开发一个功能。
  • 同时线上代码有 Bug 需要紧急修复。

基本流程:

# 1. 创建要给常驻分支
git checkout -b develop master

# 2. 基于 develop 分支,新建一个功能分支:feature/hello-world。
git checkout -b feature/hello-world develop

# 3. feature/hello-world 分支上开发
echo "feature1" >> test.txt 

# 4. 开发过程中需要先紧急修复线上代码的 bug
git stash                                         # 临时保存修改至堆栈区
git checkout -b hotfix/error master               # 从 master 建立 hotfix 分支
echo "hotfix" >> test.txt                         # 修复 bug
git commit -a -m 'fix print message error bug'    # 提交修复
git checkout develop                              # 切换到 develop 分支
git merge --no-ff hotfix/error                    # 把 hotfix 分支合并到 develop 分支
git checkout master                               # 切换到 master 分支
git merge --no-ff hotfix/error                    # 把 hotfix 分支合并到 master
git tag -a v0.9.1 -m "fix log bug"                # 在 master 分支打上 tag
scp test root@target:/opt/                        # 编译并部署代码
git branch -d hotfix/error                        # 修复完成后删除 hotfix/xxx 分支
git checkout feature/hello-world                  # 切换到 feature 分支下
git merge --no-ff develop                         # develop 有更新,需要同步更新下
git stash pop                                     # 恢复到修复前的工作状态

# 5. 继续开发
echo "feature2" >> test.txt 

# 6. 提交代码到 feature/hello-world 分支
git commit -a -m "print 'hello world'"

# 7. 在 feature/hello-world 分支上做 code review
git push origin feature/print-hello-world         # 提交到远程仓库
# 创建 PR、指定 Reviewers 进行 CR

# 8. CR 过后,由代码仓库 Matainer 将功能分支合并到 develop 分支
git checkout develop
git merge --no-ff feature/hello-world

# 9. 基于 develop 分支创建 release 分支,测试代码
git checkout -b release/1.0.0 develop
cat test.txt 

# 10. 如果测试失败,直接在 release/1.0.0 分支修改代码,完成后提交并编译部署
git commit -a -m "fix bug"
scp test root@target:/opt/

# 11. 测试通过后,将 release/1.0.0 分支合并到 master 分支和 develop 分支
git checkout develop
git merge --no-ff release/1.0.0
git checkout master
git merge --no-ff release/1.0.0
git tag -a v1.0.0 -m "add print hello world" # master 分支打 tag

# 12. 删除 feature/hello-world 分支,也可以选择性删除 release/1.0.0 分支
git branch -d feature/hello-world
# git branch -d release/1.0.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

# Forking(推荐)

常用于开源项目,开发者有衍生出自己的衍生版的需求,或开发者不固定、可能是任意一个能访问到项目的开发者。

其中 fork 操作是在个人远程仓库新建一份目标远程仓库的副本。

基本流程:

# 1. 在远程仓库上 fork 仓库:
# 比如 https://github.com/marmotedu/gitflow-demo => https://github.com/colin404fork/gitflow-demo

# 2. clone 到本地
git clone https://github.com/colin404fork/gitflow-demo
cd gitflow-demo
git remote add upstream https://github.com/marmotedu/gitflow-demo
git remote set-url --push upstream no_push # 不要 push 到 upstream master
git remote -v # 查看远程分支
# origin  https://github.com/colin404fork/gitflow-demo (fetch)
# origin  https://github.com/colin404fork/gitflow-demo (push)
# upstream  https://github.com/marmotedu/gitflow-demo (fetch)
# upstream  https://github.com/marmotedu/gitflow-demo (push)

# 3. 创建功能分支
git fetch upstream                       # 同步本地仓库的 master 分支为最新状态(与 upstream master 分支一致)
git checkout master
git rebase upstream/master
git checkout -b feature/add-function     # 创建功能分支

# 4. 提交 commit
git fetch upstream                       # commit 前需要再次同步 feature 跟 upstream/master
git rebase upstream/master
git add xxx
git status
git commit
git rebase -i origin/master              # 合并多个、保留较少的 commit
# git reset HEAD~5
# git add .
# git commit -am "Here's the bug fix that closes #28"
# git push --force

# 5. push 功能分支到个人远程仓库
git push -f origin feature/add-function

# 6. 创建 PR,请求 Reviewers review、合并到 master
# 创建 pull request 时,base 通常选择目标远程仓库的 master 分支。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  • Commit 规范
  • Header
  • Body
  • Footer
  • Revert Commit
  • 管理 Commit
  • 修改 Commit
  • 分支管理
  • 集中式
  • 功能分支
  • Git Flow(推荐)
  • Forking(推荐)