26

Git 工程化最佳实践

 4 years ago
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命令: aliassourcegrep

  • 终端的基本使用,如通过 Tab 键可以自动补全命令

  • 配置文件的使用,如Bash的 .bashrc.bash_profile , zsh 的  .zshrc ,Git 的  .gitconfig ,他们的原理都是相似的

2. 仓库创建

无论是Github还是工蜂,我们新建一个Git仓库后,往往会出现以下提示:

JJjuUny.jpg!web

某种意义上,这幅图会带来很多误解,我们在创建一个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)
  1. 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

使用效果如下:

非法分支命名

u6Bviy2.png!web

非法commit信息

emMvueY.png!web

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 键的补全机制自动选择命令,避免冗长难记的输入

ua6NFv6.gif

gs_clear_local_barnch

清理本地存在但是服务器端不存在的分支

gs_branch_last_commit

查看分支最后提交人和存活周期,辅助删除过期分支

gs_past_commit_statistic

统计过去一段时间内的代码提交数量,参数

  • $1 : 时间段或者起始时间,如 7.days2019-10-10

4. 总结

以上是笔者近期的思考总结,后面有新的想法和实践都会在此更新,欢迎关注 git-standardize。另外推荐阅读:Git内部原理剖析


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK