使用 git hook 修改 commit msg

719 阅读2分钟

前言

最近在提交代码的时候遇到一个问题,团队的 commit msg 有格式要求,要在 msg 的末尾带上关联的 jira issue,比如 refactor: optimize code (jira-project-key-12345) 或者 feat(utils): add isEmpty method (jira-project-key-12346),每提交一次都要在后面手动打上去总是一件不那么令人愉悦的事情,于是就想了一个法子,借助 git hook 自动在 commit msg 后面带上 jira issue

效果

效果如下图

image.png

可以看到我提交的时候并没有带上 jira issue,完成之后,自动带上了 jira issue 🎉

思路

我选择的 git hookcommit msg hookcommit-msg 钩子是在提交消息已经被创建之后执行的,在这个钩子中你可以比较方便地获取和校验提交消息。所以,我们可以通过这个钩子修改 commit msg

实践

安装 simple-git-hooks

这里推荐一个处理库 github.com/toplenboren…

image.png

配置 simple-git-hooks

这里贴下我的配置

# simple-git-hooks.json

{
  "commit-msg": "node commit-msg.js"
}

更新 git hook

image.png

或者通过命令

# package.json

script{
  "postinstall": "npx simple-git-hooks"
}

该钩子会在 install 之后执行,可以实现自动更新 git hooks

这里细节可以参考 github.com/toplenboren…

编辑 commit msg 脚本

团队的分支命名上也有一些要求,(type)-(version)-(jira issue)-(description),比如 hotfix-xxx-VMS-12345-refresh-account-list,所以可以通过分支名来获取 jira issue

有关 commit msg 获取可以参考 www.git-scm.com/docs/git-co…

# commit-msg.js

const { exec } = require('child_process');
const path = require('path');
const fs = require('fs');

const pattern = /VMS-\d+/;

exec('git branch --show-current', (error, stdout) => {
  if (error) {
    console.error(`exec error: ${error}`);
    return;
  }

  const match = stdout.trim().match(pattern);
  if (!match) {
    return;
  }

  const jiraIssue = match[0];

  const commitMsgPath = path.resolve(__dirname, '.git/COMMIT_EDITMSG');

  const buffer = fs.readFileSync(commitMsgPath, 'utf-8');
  const commitMsg = buffer.trim();

  if (!commitMsg.includes('VMS-')) {
    fs.writeFileSync(commitMsgPath, `${commitMsg} (${jiraIssue})`);
    fs.chmodSync(commitMsgPath, 0o0755); 
  }
});

简易方案

看了一下 simple-git-hooks 的 源码,配置的内容会被注入到指定的钩子中,比如

image.png

最后一行代码就是我添加的。

如果不想安装一个库,可以选择修改 commit-msg 这个钩子。

如果执行没有效果的话,大概率是因为没有权限,尝试执行 chmod +x .git/hooks/commit-msg

结语

如有疑问,欢迎评论。