为什么要使用 Git Hook
团队人员增加,以及项目复杂后,对于 Git 开发工作流都会有一套规范,一般都有管理代码,统一风格的类似需求。
这时候,仅仅靠成员自觉操作,出现遗漏操作的问题在所难免。
显然通过机器去每次检查会更可靠。
这次也并没有上级要求我去做这件事,现在仅仅是要求规范 git commit 的提交内容格式。格式如:
[功能] 完成聊天模块
[bug] 修复滑动越界崩溃
[修改] 修改个人文案
刚好在之前写其它脚本,听同事提过 Git Hook 的用处,我认为很适合这个场景运用。
学会使用之后,将来更可以应对更复杂的 Git 开发工作流要求当中去。
Git Hook 介绍
类似 Jenkins 之类的 CI 系统一样,Git 能在特定的重要动作发生时,去触发脚本。
借助 Git Hook 能力,可以根据各个团队自己的代码质量需求,整合到 Git 开发工作流中。
Git Hook 分类
Git Hook 也分为两个端: 客户端和服务端。
客户端的 Git Hook 就是工作在我们本地机器的,服务端的 Git Hook 则是工作在我们提交到远程的服务器仓库中。
客户端 Git Hook:
- pre-commit: 执行git commit命令时触发,常用于检查代码风格
- prepare-commit-msg: 触发于 commit message 编辑器呼起前 ,default commit message创建后,常用于生成默认的标准化的提交说明
- commit-msg: 开发者编写完并确认commit message后触发,常用于校验提交说明是否标准
- post-commit: 整个git commit完成后触发,常用于邮件通知、提醒
- applypatch-msg: 执行git am命令时触发,常用于检查命令提取出来的提交信息是否符合特定格式
- pre-applypatch: git am提取出补丁并应用于当前分支后,准备提交前触发,常用于执行测试用例或检查缓冲区代码
- post-applypatch: git am提交后触发,常用于通知、或补丁邮件回复(此钩子不能停止git am过程)
- pre-rebase: 执行git rebase命令时触发
- post-rewrite: 执行会替换commit的命令时触发,比如git rebase或git commit –amend
- post-checkout: 执行git checkout命令成功后触发,可用于生成特定文档,处理大二进制文件等
- post-merge: 成功完成一次 merge行为后触发
- pre-push: 执行git push命令时触发,可用于执行测试用例
- pre-auto-gc: 执行垃圾回收前触发
服务端 Git Hook:
pre-receive: 当服务端收到一个 push 操作请求时触发,可用于检测 push 的内容
update: update 脚本和 pre-receive 脚本十分类似,不同之处在于它会为每一个准备更新的分支各运行一次。 假如推送者同时向多个分支推送内容,pre-receive 只运行一次,相比之下 update 则会为每一个被推送的分支各运行一次。
post-receive: post-receive 挂钩在整个过程完结以后运行,可以用来更新其他系统服务或者通知用户。它的用途包括给某个邮件列表发信,通知持续集成(continous integration)的服务器,或者更新问题追踪系统(ticket-tracking system) —— 甚至可以通过分析提交信息来决定某个问题(ticket)是否应该被开启,修改或者关闭。
使用 Git Hook
Git Hook 本身自带有脚本,会存放在仓库 .git/hooks 文件夹中,目录一般是这样的:
1 | - YourGitRepo |
完整的几个 .sample 文件在可以在 Git 的开源仓库中查看: Git Hooks Sample .
可能有的人和我一样,公司的 GitLab 仓库中不会自动生成 hooks 目录,不用担心,按照上面的目录结果,在 .git 目录下建立一个 hooks 文件夹就好。
到这里,我们就可以编写 shell 脚本,针对需要的时机,来对 git 进行操作了。
注意如果是 sample 文件,要去掉 .sample 后缀,变成前面 Git Hook 分类
中提到对应的操作来作为文件名。
比如我要做的校验 commit 的提交信息,那么使用的 Git Hook 脚本名应该为 commit-msg
.
在 hooks--commit-msg.sample
里的内容为:
1 | !/bin/sh |
上面说明里有一些基本说明, 这里获得的 $1 参数,其实是存放 commit msg 内容的文件路径,为 .git/COMMIT_EDITMSG
.
利用命令:
1 | msg=$(cat $1) |
就能取到 commit 的信息,稍作修改,就能达到我说的,校验团队 commit 信息的规范的目的了。
Git Hook 不生效
如果遇到不起作用的,可能脚本没有打开执行权限,导致没办法执行。我就是这样的情况。
cd 到 .git/hooks 目录下,执行 chmod 777
命令即可,如:
1 | chmod 777 commit-msg |
由于每个团队的需求不同,就不再赘述。
我已经将 commit-msg
代码上传到 GitHub 中,感兴趣的同学可以看一看具体实现。
这一次只是很简单的对 Git Hook
的实践,它还有更多可以使用的场景,更多具体的情况还需要具体对待。