0%

使用Git-Hooks规范commit信息

1. 前言

一直以来,公司app的commit信息都比较随意,导致出了问题,查起来比较麻烦。如果有一个工具能在我们git commit之前,收集到commit信息,并判断是否符合规范,若否,则提示提交失败。幸运的是,git本身就提供了这一功能。

2. 原理

git和许多版本控制系统一样,它也拥有在特定操作之前或之后执行特定脚本代码的能力。当我们执行git init 命令生成.git文件夹的同时,也会自动生成其他文件,如branches、objects、info、hooks等。其中hooks目录保存了对应的脚本,如pre-commit.sample就是代码提交前的hook,commit之前会先执行该脚本。(注意:此处需要把后缀.sample去掉才能生效)

上方列举的都算是client端的git-hooks。其实,git-hooks支持的能力远远不止途中这些,也支持服务端git-gook。

  • applypatch-msg
  • pre-applypatch
  • post-applypatch
  • pre-commit
  • prepare-commit-msg
  • commit-msg
  • post-commit
  • pre-rebase
  • post-checkout
  • post-merge
  • pre-receive
  • update
  • post-receive
  • post-update
  • pre-auto-gc
  • post-rewrite

3. 例子

知道了上面的原理,我们就使用Android Studio(其他项目原理一样)在app代码中实现一个规范commit信息的小功能。

3.1 编写脚本

假设我们想要对commit信息做如下规范:
[commitType][module] description

其中:
commitType只能是feature(新功能)、bugfix(修复bug)、refactor(重构)、other(其他)。
module 则为对应的功能模块,如直播、视频、正文、列表等。
description没有限制。

则我们只需要编写如下脚本即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env bash
regularExpression="^\s?\[(feature|bugfix|refactor|other)\]\s?\[.+\]\s?.+"
error_msg="提交信息首行请按照如下格式书写:\n
[commitType][module] description\n
1. commitType只能是feature(新功能)、bugfix(修复bug)、refactor(重构)、other(其他)
2. module 则为对应的功能模块,如直播、视频、正文、列表等
3. description 没有限制
例如:
[feature][列表] 新增头图广告 "
#获取文件首行
firstLine=`head -n1 "$1"`
if [[ "$firstLine" =~ $regularExpression ]]; then
echo "commit success"
exit 0
fi
echo "commit fail"
echo "$error_msg" >&2
exit 1

原理非常简单,就是取出commit信息的第一行,然后正则匹配即可。只要把该脚本拷贝到工程的.git/hooks目录下,并重命名为commit-msg,同时增加可执行权限,便大功告成!

3.2 修改gradle文件

如果你嫌麻烦,找不到.git目录(.git目录是默认隐藏的),可以通过修改gradle文件,配合另一个脚本,便会自动把上述脚本拷贝到.git/hooks/目录下了。这样做的好处是,你自己只需要把当前修改提交上去,全组的同事拉下最新代码,就生效了!

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
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.netease.githooksdemo"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
// 额外添加的,在build之前检查一下githook脚本是否存在
afterEvaluate {
tasks.matching {
it.name.equals("preBuild")
}.each {
it.doFirst {
exec {
executable 'chmod'
args 777, 'githook/installGitHook.sh'
}
exec {
executable ('githook/installGitHook.sh')
}
}
}
}
}

其中,installGitHook.sh脚本代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env bash
gitHookPath='.git/hooks/commit-msg'
# 获取当前脚本所在的父目录,即githook
rootPath=$(cd `dirname $0`;pwd)
cd "$rootPath"
cd ..
cd ..
# 将目录定向到根目录下,即GitHooksDemo
rootPath=`pwd`
if [ ! -d ".git/hooks" ]; then
mkdir .git/hooks
fi
# 判断原来的bash脚本是否存在,如果存在无需复制一遍
# 如果不需要实时更新,把If条件加上即可.
#if [ ! -f "$gitHookPath" ]; then
# 复制当前脚本到git-hooks目录下
cp ${rootPath}/app/githook/pre_commit.sh '.git/hooks/commit-msg'
# 修改权限
chmod a+x '.git/hooks/commit-msg'
#fi
exit 0

如果我们提交的格式有误,Android Studio 便会提示commit失败:

4. 源码下载

GitHookDemo

5. 参考