Git使用规范

大约 13 分钟

Git使用规范

作 者: Luke

日 期: 2022-12-17

1. 配置规范

公司Git上的代码、资料均作为公司资产,严禁在Github、公开Gitlab、Geete等公共平台上分享使用

1.1 环境配置

Gitlab网站用户名和邮箱按规则命名

  • 用户名: xing_ming
  • 邮箱(海外): xing_ming@stationdm.com
  • 邮箱(国内): xing_ming@woodare.com

本地配置的用户名和邮箱按规则命名

  • 用户名: xing_ming
  • 邮箱: xing_ming@internal.dev

例如:蒋新星(jiang_xinxing)的设置如下:

  • 用户名: jiang_xinxing
  • 邮箱: jiang_xinxing@internal.dev

注意事项

  • 开启二次身份验证
  • 更换电脑,尤其是临时应急环境,检查确认仓库的使用配置信息
  • 多个软件并行使用时,注意配置的本地个人信息
  • 清理过期、冗余的个人gitlab下的SSH配置,仅保留近期还是使用的

1.2 注意事项

信息不一致(本地用户、Git账号)

  • 推送记录显示的非本人姓名 (未配置)
  • 提交记录显示的其他人姓名 (未配置)
  • 同一个项目出现同人不同名 (多系统、多软件配置差异)
  • 不同项目内出现同人不同名 (未开启全局配置)

1.3 项目现状

案例:高企培育

  • 贡献人

代码贡献«

案例:BI产品

  • 贡献人

代码提交«

案例:Conductor

  • 贡献人

代码提交«

1.3 软件工具

推荐工具

  • Sourcetree

可选工具

  • IDE集成环境 (IDEA, VSCode, XCODE)
  • Git命令行

2. 分支规范

2.1 分支规则

  • 版本演进次序,按照 dev[feature|hotfix] -> develop -> release -> master

    • master 分支,用于生产发布 ( Prod |UAT )
    • release 分支,用于集成验证 ( Prod |UAT |QA )
    • develop 分支,用于开发集成 ( DEV |UAT |QA )
    • feature/** 分支,用于功能模块专有开发,需合并进develop分支
    • hotfix/ 分支,用于紧急版本发布,需同时合并进release测试验证后,再并入master发布**
  • 禁止在master、release上进行rebase、commit等操作,仓库应锁定对应权限

  • 禁止在develop进行rebase等操作,原则上应仅包含commit、feature与hotfix分支的merge

  • 临时分支(除以上列出),用于个人临时暂存代码,原则上必须1周内通过rebase至顶端后再合并, 且仅保留一次commit

  • 功能分支,用于单个或固定几个功能的短期开发,原则上进行rebase至顶端后再合并

2.2 标签定义

  • 通常发布Prod才需要做TAG。 TAG以版本号和M(n)形式命名,如: v1.1.0v1.1.0-M1
  • 特例发布UAT(QA)(给客户POC使用时),采用Q命名方式如: u3.1.0u3.1.0-M1
  • 打完标签后此标签里面的内容不作任何修改

2.3 项目现状

案例:高企培育后台

分支管理« 分支管理« 分支管理«

案例:Junction平台

分支管理« 分支管理« 分支管理«

案例:Kintaro平台

分支管理« 分支管理« 分支管理«

案例:TSP平台

分支管理« 分支管理« 分支管理«

3.提交规范

3.1 提交规则

  • 工作分支 应该每天拉取,及时同步项目代码和变化
  • 提交信息必须 清晰、准确 ,禁止使用 无意义、重复性 描述信息
  • 严禁将代码滞留在本地,应基于 临时分支 及时上传至仓库;
  • 临时分支 仅为临时用途,基本原则一周内必须做代码合并
  • 功能分支 作为短期工作分支,用于复杂功能无法短时间或一次完成

3.2 项目现状

案例:描述无意义

提交描述«

案例:描述无意义

提交描述«

案例:描述重复提交

提交描述«

4. 合并规范

请考虑这个场景,当你开始在一个专有的分支开发新的功能时,另一位团队成员更新了main分支的内容。这将会造成一个分叉的提交历史,对于任何一个使用Git作为代码协作工具的人来说都不会陌生

  • 关键词:branch、**feature/、**dev/、merge、rebase、cherry-pick、pull|push、commit
  • 常见场景:拉取最新代码、上传本地代码、代码未完结上传、拉取后编译异常、提交遇到代码冲突、申请代码合并(PR|MR)、版本回滚

4.1 使用 merge

最简单的方法就是把main分支合并进功能分支:

git checkout feature
git merge main

或者用下面这样的单行命令:

git merge feature main

这会在feature分支中创建一个合并提交,这次提交会连结两个分支的提交历史,在分支图示结构中看起来像下面这样

提交描述

4.2 使用 rebase

git rebase是用来处理git merge命令所处理的同样的问题。

这两个命令都用于把一个分支的变更整合进另一个分支——只不过他们达成同样目的的方式不同。

对比merge操作,可以把feature分支的提交历史rebase到main分支的提交历史顶端:

git checkout feature
git rebase main

这些操作会把feature分支的起始历史放到main分支的最后一次提交之上,也达成了使用main分支中新代码的目的。但是,相对于merge操作中新建一个合并提交,rebase操作会通过为原始分支的每次提交创建全新的提交,从而重写原始分支的提交历史。

rebase

4.3 可交互式rebase

可交互式rebase让你在把变更提交给其他分支之前有机会对提交记录进行修改。 通常来说这一操作的使用场景在于合并功能分支到main分支之前,对于功能分支杂乱的提交记录进行整理。

进行可交互式rebase操作,需要向git rebase命令传递i选项参数

git checkout feature
git rebase -i main

执行以上命令会打开一个文本编辑器,其中内容为分支中需要移动的所有提交列表:

pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

上面这样的列表正表示了分支被rebase之后其历史的长相。通过修改pick命令或者对提交历史进行重新排序,你可以让最终的提交历史变成任何你希望的样子。比如说,如果第二次提交修复了第一次提交的什么BUG,你可以使用fixup命令替代pick来把两次提交压缩在一起。

pick 33d5b7a Message for commit #1
fixup 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3
rebase

4.4 rebase黄金法则

一旦你明白了什么是rebase,接下来最重要的事情就是要了解什么情况下不应该使用它。关于git rebase的黄金法则就是永远不要在公共分支上使用它。

举例来说,想一想如果把main分支rebase到feature分支之上,会发生什么:

rebase

rebase命令会把main分支中的所有提交都放到feature分支的提交记录顶端。问题在于这个改变目前只出现在你的本地仓库。其他开发者仍然在原来的main分支上进行开发。由于rebase会产生全新的提交记录,所以Git会认为现在你本地的main分支与所有其他人的产生了分叉。

唯一能够同步两个不同的main分支的方式就是将其合并起来,这会产生一个冗余的合并提交,并且这次合并中的大部分提交内容都是相同的(以前的main分支和你本地的main分支中)。

4.5 本地清理

在现有工作流中包含rebase操作的最适合的场景之一是:清理本地正在进行中的开发分支。通过定期使用可交互rebase操作,可以清理本分支的提交记录,让每一次提交都更加聚焦并有意义。可交互rebase操作允许你在写代码的时候不用太在意提交历史,事实上你可以在事后再对提交历史进行清理。

当使用git rebase命令时,有两种选项可以作为新的base:功能分支的父分支(比如 main 分支),或者是本分支内历史中的某一次提交。第一种情况的示例我们在交互式rebase的段落见到过。后一种选项对于修改本分支内的提交历史则相当有用。比如下面的命令会开启一次对于最近三次提交历史的rebase操作。``

git checkout feature git rebase -i HEAD~3

通过指定HEAD~3作为rebase操作的新base,你并不是在实际移动分支——你只是以交互的方式对HEAD~3这次提交之后的三次提交历史进行重写。注意这个操作并不会将上游的修改引入feature分支:

rebase

4.6 引入上游的修改

我们讨论过如何通过git merge或者git rebase方式引入上游main分支的修改。merge操作足够安全,因为它保留了完整的提交历史,但是rebase操作通过将功能分支的提交历史移到main分支的顶端从而创建了线性的提交历史。

此种对于git rebase操作的使用与清理本地提交历史类似(也可以同时操作),差别在于在执行过程中会引入上游main分支的提交。

请记住rebase可以对任何远端分支进行操作,并不仅限于main分支。比如当你需要与其他人协作开发一个功能时,你可以通过rebase来引入其他人的开发内容。

比如说,当你和另一个名叫John的开发者都对feature分支进行了提交动作,在你fetch远程的feature分支之后,本地仓库应该看起来是下图这样的:

rebase

为了整合这个分叉,你可以像对待main分支一样:要么通过merge操作将john/feature分支合并到本地feature分支,或者rebase本地feature分支到john/feature分支的顶端。

rebase

请注意这并不与rebase的黄金法则发生冲突,因为只有你本地的feature分支的新提交被移动到john/feature分支的顶端,新提交之前的所有提交历史都没有变化。这就好像说:“把我提交的新内容添加到John已经提交的内容之上。”在大多数情况下,这种操作比使用merge操作更符合人类的直觉。

git pull命令默认行为是进行一次合并操作,但你可以通过添加--rebase选项指定pull操作的行为为rebase。

4.7 使用pull request进行功能审查

如果你使用pull request来进行代码审查工作,那么在创建了pull request之后应该避免使用git rebase。一旦你创建了pull request,其他开发者就会来查看你的提交,也就意味着此时的分支算作是一个公共分支了。那么此时重写提交历史,则会让Git和团队成员无法判断哪些提交是属于这个功能的。

引入任何他人的修改时,应该使用git merge而不是git rebase。

因此在提交pull request之后进行一次交互式rebase来清理提交历史通常是一个好主意。

4.8 整合审查通过的功能

被团队审查通过的功能代码,可以先使用rebase将新代码移动到main分支的顶端,然后在进行git merge合并新功能到main分支中。

这个操作跟rebase上游分支到本地功能分支类似,只是由于你不能重写main分支的提交历史,所以你只能在最后通过git merge操作来把功能分支的代码整合进main分支。不过在合并之前进行一次rebase,可以保证这次merge操作是可以快速前进的,这样提交历史看上去就是完美的线性。这也给你机会可以在真正合并之前进行一次提交历史的清理。

rebase

如果你还不是很适应git rebase操作,那么总是可以利用一个临时分支来进行rebase操作。这样的话,万一你不小心搞乱了功能分支的提交历史,总还有兜底的机会从原始的功能分支再来一遍。就像下面这样:

git checkout feature
git checkout -b temporary-branch
git rebase -i main

# [Clean up the history]
git checkout main
git merge temporary-branch
上次编辑于:
贡献者: luke,lu_feng