您的位置:

Git Hooks详解

一、githooks权限

Git Hooks是在Git版本控制的基础上,提供了一些钩子(hooks),可以在一些关键的节点上执行特定的自定义脚本。这些脚本代码会自动执行,不需要手动操作,非常方便。而Git Hooks的权限管理主要分为两种:

第一种是全局权限,表示该Git Hooks是系统级别的,并会对所有的仓库生效。可以在用户主目录下的.gitconfig文件中对其进行配置设置。

第二种是局部权限,表示该Git Hooks只在特定的仓库中生效。可以在该仓库下的.git/hooks目录中对其进行配置。这种方式的优先级高于全局权限,如果同一仓库下全局和局部同时配置了Git Hooks,就会以局部的为准。

二、githooks husky

Husky是一款流行的Git Hooks工具,可以帮助我们更方便地管理项目中的Git Hooks脚本。Husky提供了一系列钩子命令,比如pre-commit、pre-push、commit-msg等,在特定的事件节点上自动执行我们编写的脚本。

使用Husky还需要先安装husky包,执行npm install husky -D即可。安装完成后在package.json文件中对husky进行配置(也可以在.git/hooks中手动创建脚本):

{
  "husky": {
    "hooks": {
      "pre-commit": "npm run lint",
      "prepare-commit-msg": "node build/scripts/prepare-commit-message.js"
    }
  }
}

三、githooks没执行

有时候我们在执行Git Hooks的脚本时,会遇到脚本没有执行的情况。这种情况可能是因为Git Hooks脚本没有执行权限。我们可以通过执行chmod +x .git/hooks/*命令,为所有的Git Hooks脚本添加可执行权限。如果想要针对单个脚本添加权限,可以执行chmod +x .git/hooks/pre-commit命令。

四、githooks发送邮件

Git Hooks还可以配合其他的工具来实现更加复杂的操作,比如发送邮件通知。我们可以通过使用Git Hooks中的post-receive钩子,在代码推送后触发一个脚本,来实现发送邮件的功能。

发送邮件的脚本可以使用node执行,内容可以参考下面的代码片段:

#!/usr/bin/env node

const child_process = require("child_process");
const nodemailer = require("nodemailer");

// 获取git提交信息
const commitMsg = child_process.execSync("git log -1 --pretty=tformat:%s").toString().trim();

// 发送邮件
const transporter = nodemailer.createTransport({
  host: "smtp.ethereal.email",
  port: 587,
  auth: {
    user: "
   ",
    pass: "
    ",
  },
});
const mailOptions = {
  from: "
     ",
  to: "
      ",
  subject: "New commit from Git repository",
  text: commitMsg,
};
transporter.sendMail(mailOptions, function (error, info) {
  if (error) {
    console.log(error);
  } else {
    console.log("Email sent: " + info.response);
  }
});
      
     
    
   

五、githooks检验提交信息

有时候我们希望在提交代码时,对提交信息进行检验,比如限制提交信息的长度、格式等等。通过使用Git Hooks中的commit-msg钩子,我们可以在提交代码之前执行一个脚本来实现检验。commit-msg脚本会在Git中的message文件中读取提交信息,可以对提交信息进行修改或者检验。如果提交信息不符合要求,可以通过exit 1命令来制止提交操作。

下面是一个检验提交信息格式的示例代码:

#!/usr/bin/env node

const fs = require('fs');

const COMMIT_MSG_FILE = process.argv[2];
const commitMsg = fs.readFileSync(COMMIT_MSG_FILE, 'utf-8');

const pattern = /^([A-Z]+-[0-9]+): (.*[^\.])$/gm;
if (!pattern.test(commitMsg)) {
  console.log('Invalid commit message! Format should be: 
   : 
    ');
  process.exit(1);
}
    
   

六、githooks怎么停止push

有时候我们在执行Git Push操作时,可能会遇到一些问题,比如代码有冲突、不符合规范等等。在这种情况下,我们希望能够停止Push的操作,以免引起更加严重的问题。这时,我们可以使用Git Hooks中的pre-push钩子,在Push操作之前执行一些检查,如果检查失败,就可以采取措施终止Push操作。

下面是一个终止Push操作的示例代码:

#!/bin/bash
while read local_ref local_sha1 remote_ref remote_sha1
do
  if [[ "$local_ref" = "refs/heads/master" ]]; then
    echo "Push to master branch is disabled!"
    exit 1
  fi
done

七、githook设置commit-msg

在一些项目中,规范的提交信息是非常重要的。为了保证每个开发者提交的信息都符合规范,我们可以使用Git Hooks中的commit-msg钩子,在提交代码之前执行检验。一般情况下,我们会规定提交信息的格式,比如以项目编号+冒号+提交信息的方式提交。commit-msg钩子脚本可以自动验证提交信息的格式是否符合规范,如果不符合就停止提交。

下面是一个设置commit-msg格式的示例代码:

#!/bin/bash
COMMIT_REGEX='^[A-Z]+-[0-9]+: ';

while read line
do
  if ! [[ "$line" =~ $COMMIT_REGEX ]]; then
    echo "Invalid commit message format. Should be '
   : 
    '."
    exit 1
  fi
done < "${1:-/dev/stdin}"
    
   

八、Git Hooks代码检查

在代码开发过程中,代码风格的一致性和代码质量的保证非常重要。我们可以使用Git Hooks中的pre-commit钩子,在代码提交之前执行一些代码检查脚本,来保证代码的质量和一致性。常用的代码检查工具有ESLint、Prettier、Stylelint等。

下面是一个使用ESLint进行代码检查的示例代码:

#!/bin/bash

FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.jsx\?$')

# ESLint check
if [[ $FILES = "" ]] ; then
    exit 0
fi

pass=true
for FILE in ${FILES}; do
    git show ":$FILE" | eslint "$FILE"
    if [[ "$?" != 0 ]]; then
        pass=false
    fi
done

if ! $pass; then
  echo "ESLint check failed, please fix errors before committing."
  exit 1
fi