不会写shell的程序员照样是好前端——用Node.JS实现git hooks

数据部
• 阅读 6698

git hooks想必很多攻城狮都不陌生,官方对于hooks有详细的文档,也有站内网友的文章Git Hooks (1):介绍,GIt Hooks (2):脚本分类,说的非常详细了,这里就不多做介绍,这里主要介绍一下如何写一个hook。

一个基本的git hook长什么样?

对git-hooks有一个入门认识的朋友都知道,hooks存放在git仓库的.git/hooks目录下,其中包括很多hooks,这些是在git 仓库创建的时候自动生成的,后缀名统一都是.sample,表示这些hooks都是默认不启用的,当把后缀名去掉之后,就变成了可以使用的hook。

举个栗子

不会写shell的程序员照样是好前端——用Node.JS实现git hooks

pre-commit这个hook是在git commit的时候触发的hook,这个hook里面写了什么呢?代码我就不贴了,没啥劲,主要的几点就是:

  1. 这是一个shell脚本

  2. 这个脚本运行了一些东西然后退出了

  3. 退出的时候退出的错误码不是确定的

这就是一个hook的最基本的组成:在命令行执行git操作的时候,自动执行hooks目录下相应的可执行脚本,然后根据脚本的退出状态决定此次操作是否成功。当退出的错误码不为0的时候,表示失败,操作终止,否则操作继续。

模拟场景

如果现在有这样一个场景,在你的git仓库里,要求不允许提交dist目录,并且通过mocha的测试,否则不允许提交,用git hook 怎么做呢?

首先,这是在提交的时候的一个限制,所以应该考虑使用pre-commit这个hook,代码就不写了(不会写shell... Orz),整个过程如下:

  1. 检查是否有dist目录,如果没有的话下一步,否则退出,错误码置为1。

  2. 执行mocha命令进行测试,如果测试全部通过的话,退出,错误码为0,否则错误码为1,同样退出。

这样,当上述任何一步没有通过的时候,这个hook就会被终止,git-commit就无法通过,也就达到了限制提交的目的。

shell脚本的局限性——不会写

作为一名普通的前端,兼,一名不太合格的工程师,我对于shell脚本实在是不熟悉,连Linux命令都玩不转,别说写出666的shell脚本了,囧~ 所以要另辟巧径做这件事。

前端仔们对js应该是非常熟练的,所以如果能用js写hooks,那不就爽了?而Node.JS正好给了我们希望,感激涕零的话就不多说了,绝对感动到哭!

不会写shell的程序员照样是好前端——用Node.JS实现git hooks

Node.js写起脚本来也非常简单,比如一个最简单的脚本

#!/usr/bin/env node

console.log('Hello World!');

给脚本赋予可执行权限之后就完全可以当做shell脚本来跑了,麻麻再也不用担心我不会shell了。同样的,在hooks中我们也可以这样用。再举个栗子

不会写shell的程序员照样是好前端——用Node.JS实现git hooks

还是刚才的场景,不允许有dist目录,同时通过所有mocha测试,用Node就可以这样写(这次我能show出代码了)

#!/usr/bin/env node
var fs = require('fs'),
    spawnSync = require('child_process').spawnSync;
if(fs.existsSync('./dist')){
    console.log('Commit Abort!Please remove dist directory.');
    process.exit(1);
}
// 使用同步方法spawnSync执行mocha,测试的结果在result.status中,通过为0,不通过为1
var result = spawnSync('./node_modules/.bin/mocha',['test']); 
if(result.status){
    console.log('Commit Abort!Test failure.');
}
process.exit(result.status);

这就是一个用Node.JS实现的基本的git-hook。

Node.JS的局限性——不能动

client-side hook的一个问题就是没法在随着仓库变动,如果项目成员多的话,每个人都需要在自己本地添加一次,hooks有变动了更新也比较麻烦。

解决方案

我个人对这个问题有一个简单解决方案,我做了一个仓库git-hooks-node,每次写好git hooks之后通过自己写的工具进行build,生成一个类似于安装器的文件,然后提交到远程仓库,如pre-commit.js是hook具体的内容,pre-commit.installer.js是生成的安装文件,也是一个脚本,github上的每一个文件都有相应的raw地址,如这个安装文件的地址为raw pre-commit.installer.js,然后mac OS下的用户就可以使用curl获取脚本并运行,如下:

curl https://raw.githubusercontent.com/y8n/git-hooks-node/master/xgfe-ma/pre-commit.installer.js | node

安装效果如下

不会写shell的程序员照样是好前端——用Node.JS实现git hooks

这样只要写好一个hook并发布,项目成员只要知道地址就可以一键安转(想想还有点小激动呢)。这样虽然没有解决hook不会随着仓库移动的问题,但也提供了一种在项目组里通用一套hook的方案。

其他解决方法

husky是GitHub上一个开源项目,它的做法是在npm install这个模块的时候自动在.git/hooks目录下创建很多hooks,然后再在package.json中指定每一个hook的执行脚本,如下

"scripts": {
    "precommit": "npm test",
    "prepush": "npm test",
    "commit-msg": "./validate-commit-msg.js",
    "...": "..."
  }

这样就可以把hooks随着项目变动,真正做到项目成员共用一个git hook,但问题就是必须在项目中依赖husky,不过想想这样的方法也比上面我的方法高明许多 -.-!

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
11个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(