Git 工程化最佳实践
source link: https://mp.weixin.qq.com/s/-0wr_9iH55qlP31c89uP3w
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
1. 本文导读
本文对应的 git-standardize 项目地址 https://github.com/vimerzhao/git-standardize
1.1. 问题背景
大部分程序员对于Git的理解还停留在
git add . git commit -m "update" git pull git push
的阶段,但这在实际项目开发中是远远不够的。
举一个简单的例子,现在我们需要过滤所有修复bug的提交,该怎么做?显然是无法做到的,因为无法从commit信息获知。但是,如果我们在每次commit信息里面都注明提交的类型,是不是就可以通过过滤指定类型来达到目的了。
再举一个例子,如果我们的分支命名都是
master-01 master-02 feature-add_sd_card_permission bugfix-id-342141 bugfix-authorize-error
这种格式,我们是不是很不方便去做 定位分支的负责人,过滤指定分支 等操作,更不用说视觉上的混乱所造成的困扰了。
再比如,笔者近来发现某个仓库有大量构建产生的中间文件,究其原因,发现是因为管理人员设置的 .gitignore
配置如下
.... /build ....
显然,这种写法无法忽略子模块的 build 目录。
基于以上三个例子,Git使用的工程化、标准化是十分必要的。
我们所谓的造轮子,亦不仅仅存在于编程中,日常工作中常有大量的重复工作,亦是一种轮子,本文即 希望规范化、流程化Git的使用 ,以期提高开发者的效率。
本文基于作者工作中的教训和思考积淀而成,虽曰“最佳”,但也只是现阶段我心中的最佳实践,仅供参考。
1.2. 阅读须知
Git的作者Linus也是Linux的作者,Git最初也是Linux内核开发者在使用,所以其本身的配置和使用也是充满了类Unix的味道,诸如别名、命令、配置文件等等,都是Unix/Linux开发者习以为常的东西,但对于客户端、大前端的开发者可能相对陌生,所以,继续阅读本文之前,希望你对以下知识至少是有了解的
-
基本的Shell命令:
alias
/source
/grep
等 -
终端的基本使用,如通过
Tab
键可以自动补全命令 -
配置文件的使用,如Bash的
.bashrc
/.bash_profile
, zsh 的.zshrc
,Git 的.gitconfig
,他们的原理都是相似的
2. 仓库创建
无论是Github还是工蜂,我们新建一个Git仓库后,往往会出现以下提示:
某种意义上,这幅图会带来很多误解,我们在创建一个Git仓库后还有很多事情要做,一开始,我们或许习惯于渐进式的改进,但我们应该意识到这种工作是可以 流程化、自动化 的,即不要等到发现问题再去解决,而应该一开始就建立有效、可复用的机制。
2.1. 信息配置
使用 git config
配置必须要的用户信息
反面案例:
腾讯内部每个员工有自己的英文名和tencent邮箱,但是部分开发人员未注意,导致诸如 name(中文名) [email protected] 的信息进入了提交历史
2.2. gitignore
github-gitignore 提供了各类型项目的 .gitignore
模版,基本可以直接使用,如需定制,参考 Git - gitignore Documentation ,确保自己理解了语法规则。一般而言,本地的配置、编译生成的中间文件是需要在项目建立之初就添加 .gitignore
的。
2.3. 分支规范
只允许使用以下分支命名项目
-
master
-
主分支,也是用于部署生产环境的分支,确保
master
分支稳定性,任何时间都不能直接修改代码
-
-
release
-
release
为预上线分支,发布提测阶段,会以release
分支代码为基准提测 -
分支命名细则:
release-version
-
当有一组
feature
开发完成,首先会合并到master
分支,进入提测时,会创建release
分支 -
如果测试过程中若存在bug需要修复,则直接由开发者在
release
分支修复并提交 -
当测试完成,经过一个周期的灰度之后,合并
release
分支到master
分支 -
release
分支的最终状态是每个线上版本的归档镜像
-
-
hotfix
-
线上出现紧急问题时,需要及时修复,以
master
分支为基线,创建hotfix
分支,修复完成后,需要合并到master
分支和处于待发布的release
分支 -
分支命名细则:
hotfix-creator-description
-
-
feature
-
开发新功能时,以
master
为基础创建feature
分支 -
分支命名细则:
feature-creator-description
-
Warning
是否需要引入develop
分支以维持 master
分支的稳定性(上述机制的不足之处)有待商榷,过于复杂也不是一件好事,保证 合入分支自身的质量 看起来是更好的解决方案
推荐一篇参考文章 A successful Git branching model » nvie.com
2.4. commit规范
参考 angular.js commit规范
针对客户端的每次提交限制格式如下
<type>(<scope>):<subject> # (1) (2) (3) <BLANK LINE> <body> (4) <BLANK LINE> <footer> (5)
-
type
:本次改动的类型
-
feat: 添加新特性
-
fix: 修复bug
-
docs: 仅仅修改了文档
-
style: 仅仅修改了空格、格式缩进等,不改变代码逻辑
-
refactor: 代码重构,没有加新功能或者修复bug
-
perf: 增加代码进行性能测试
-
test: 增加测试用例
-
chore: 改变构建流程、或者增加依赖库、工具等
scope
:本次改动影响的范围,建议每个工程划分好自己的模块,方便填写
subject
:本次改动的简要描述,一般写这个就够了
body
:更详细的改动说明,一般不使用,因为不推荐这么大的改动
footer
:描述下与之关联的 issue 或 break change,一般不使用
Note
建议
-
建议每次commit的粒度不要太大,方便CodeReview
-
fix
类型的提交最好附带上bug链接之类的信息
2.5. GitHook
GitHook应该在仓库创建之后尽早设置,为了避免重复工作,笔者以及针对上文提到的信息配置、分支规范和commit规范等提供了 强制检查 的能力,引入方式如下
cd .. git clone http://git.code.oa.com/vimerzhao/git-standardize.git cd - cp -R ../git-standardize/.githooks ./ cd .githooks chmod +x *[^rule] cd .. git config core.hooksPath .githooks cd .. rm -rf git-standardize cd -
如果管理员配置好了hook并完成了服务器端的push,那么对于其他开发者,只需要
git pull --rebase git config core.hooksPath .githooks
使用效果如下:
非法分支命名
非法commit信息
3. 仓库使用
3.1. gitconfig
参考 Git - Git Configuration
3.2. GitHook
如上所述,使用者clone下仓库后应该配置本地GitHook,避免不小心提交脏信息
git clone **** git config core.hooksPath .githooks
3.3. 别名设置
下文会专门论述为什么推荐你在命令行而不是GUI工具中使用Git,本章主要讲述如何使用别名。别名在类Unix系统中普遍存在,即将我们最常用的命令设置一个更短更容易记住的别名,以提高使用效率。
oh-my-zsh
zsh是一款类似于 GitBash 的终端软件,而 oh-my-zsh 则是基于 zsh 深度定制的版本,其 git
插件提供了一套别名,推荐使用,避免重复造轮子。
文档位置:git-cheatsheet
配置位置:git.plugin.zsh
使用这套别名可以有以下好处
-
省力省心,开源社区长期优化的配置大概率比我们自己折腾的更加科学和健壮
-
通用性强,任何一个使用 oh-my-zsh 的用户和你的别名习惯都是一致的,便于交流
GitBash
如果开发环境是 Mac/Linux ,强烈推荐使用 oh-my-zsh,如果是 Windows,目前看来还是使用 GitBash 最佳,推荐将 git.plugin.zsh 的别名规则平移到 GitBash 下,这样也符合上文提到的通用性原则。移植方法很简单,如下
# 大意如此,视具体情况可能需要稍作修改 move path/to/oh-my-zsh/plugins/git/git.plugin.zsh ~/.git.plugin.zsh echo `source ~/.git.plugin.zsh >> .bash_profile`
GitAlias
GitBash 使用 Linux别名 时有一个不太友好的问题,就是不支持自动补全,对于像 git checkout
这样的命令,非常需要自动补全,否则很容易拼错分支名称。
所以推荐配置
Git别名
,为了提高通用性,Git别名同样推荐基于 oh-my-zsh 的别名规则进行移植,下面是一段 git.plugin.zsh 的Linux别名配置
... alias gbr='git branch --remote' alias gbs='git bisect' alias gbsb='git bisect bad' alias gbsg='git bisect good' ...
很容易发现,每个别名均以 g
开头以区分其他命令,而 GitAlias 均以 git
开头,所以对应的Git别名配置可以是
... git config --global alias.br 'branch --remote' git config --global alias.bs 'bisect' git config --global alias.bsb 'bisect bad' git config --global alias.bsg 'bisect good' ...
如此一来, git branch --remote
这个命令在 Mac/Windows/Linux 均可以通过 gbr
或者 git br
访问到。
Note
Linux别名:通过bash命令 alias
设置。
Git别名:通过 git config --global alias
设置。
Note
如何移植 git.plugin.zsh?一行一行的修改 alias
语法为 git config alias
语法吗?笔者的解决方法
# 提取所有关于别名的配置,并暂存 grep -E "alias g[a-zA-Z]+=.*" path/to/git.plugin.zsh > temp1.sh # 改成GitAlias风格的别名 sed "s/^alias g/git config --global alias./g" temp1.sh > temp2.sh # 去掉命令里面的 `git`,符合 GitAlias 语法 sed "s/git //g" temp2.sh > git.alias.config.sh # 进行配置,运行后会注册到 .gitconfig source git.alias.config.sh # 删除中间文件 rm temp*
3.4. 命令封装
所有的辅助命令均以 gs_
开头,这样的好处是可以利用 Tab
键的补全机制自动选择命令,避免冗长难记的输入
gs_clear_local_barnch
清理本地存在但是服务器端不存在的分支
gs_branch_last_commit
查看分支最后提交人和存活周期,辅助删除过期分支
gs_past_commit_statistic
统计过去一段时间内的代码提交数量,参数
-
$1 : 时间段或者起始时间,如
7.days
、2019-10-10
4. 总结
以上是笔者近期的思考总结,后面有新的想法和实践都会在此更新,欢迎关注 git-standardize。另外推荐阅读:Git内部原理剖析
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK