不要让💩滑入您的代码库!

512 阅读4分钟

多人协作开发时经常会遇到拉下来的代码编译报错了;拉下来都别人的调试代码影响开发体验;查找git代码提交记录时都是写的aaa等没有一点价值的commit-msg。本文基于Git Hooks来解决这些问题。

Git Hooks

git hooks,即git 钩子,定义为能在特定的重要动作发生时触发自定义脚本。

我们可以在git仓库中 .git/hooks文件夹中看到git hooks脚本文件。可以更改这些文件插入我们自己的脚本来实现我们的需求。但是直接使用git-hooks 编写成本高,无法共享(.git 文件夹是不会提交到代码仓库的)。husky可以让git hooks 的使用更简单。安装过程建议参考官方文档typicode/husky: Git hooks made easy 🐶 woof! (github.com)

下面是 husky 使用后示例图,可以直接在项目中看到 .husky/ 文件夹中都是对应的git hooks image.png 安装

npm install husky -D

添加到package.json 中,这样别人下载代码时也会安装husky

npm set-script prepare "husky install"
npm run prepare

添加一个钩子

npx husky add .husky/pre-commit "npm test"
git add .husky/pre-commit

添加如下命令就可以在代码commit 之前执行代码检查。 lint检查并修复后,使用git add . 重新添加到暂存区。

# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint
git add .

Lint Staged

上面我们已经可以实现代码检查了,但是每次都会对项目中所有的文件执行一次代码检查,是没有必要的。并且git add . 也是有缺陷的,会把所有文件添加到暂存区。

对暂存的 git 文件运行 linters,不要让💩滑入您的代码库!

——来自lint-staged官方

在提交代码之前运行时,Linting 更有意义。通过这样做,您可以确保没有错误进入存储库并强制实施代码样式。但是,在整个项目上运行 lint 过程很慢,并且 lint 结果可能无关紧要。最终,您只想删除将要提交的文件。lint staged 可以让你的代码检查,只检查暂存区的代码,不会校验所有文件。而且修复后如果文件有改动,会自动重新执行git add当前文件提交到暂存区。

安装

npm install --save-dev lint-staged

在根目录创建 .lintstagedrc.json

# .lintstagedrc.json
{
  "*.{js,ts,vue}": [
    "npx eslint"
  ]
}

或者在package.json 中添加

// package.json
{
    "lint-staged": {
      "*.{js,ts,vue}": [
        "npx eslint"
      ]
    }
}

修改 pre-commit

# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged

确保npm script已经有 lint,本文不介绍eslint

规范commit-msg

在git-hooks 的comit-msg 钩子中我们可以去做msg的校验,同样直接编写会比较复杂。commitlint 可以让实现更简单,具体使用推荐参考官方文档 Local setup (commitlint.js.org)

安装

npm install --save-dev @commitlint/config-conventional @commitlint/cli

@commitlint/config-conventional 是一种共享的message配置,还有很多commitlint/@commitlint at master · conventional-changelog/commitlint (github.com),选择适合自己的,也可以自定义配置

添加配置文件

echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js

or 手动配置

# commitlint.config.js
module.exports = {
  extends: ["@commitlint/config-conventional"],
};

这样在 git commit 提交时就必须按照msg提交格式来提交了。

推荐的msg格式

type(scope?): subject 
body? 
footer?

type不知道使用哪个?commitlint/index.js at master ·conventional-changelog/commitlint (github.com)

如果记不住,可以使用msg提示工具,Use prompt (commitlint.js.org)或者commitizen/cz-cli: The commitizen command line utility. #BlackLivesMatter (github.com)

自动删除调试日志

webpack 可以配置在build时删除console.log 和 debugger 等调试代码。但是只能在build的时候处理。多人协作开发时,拉下来别人忘删除的调试代码也是很常见的。所有我们也可以在lint-staged 中解决这个问题,在提交之前删除调试日志。

修改lint-staged

{
  "*.{js,ts,vue}": [
    "node ./misc/checkLog.js",
    "npx eslint"
  ]
}

删除log一定要在lint 之前。这样删除后,lint --fix 时可以修复代码格式问题

lint-staged 的调用,会把文件名当作参数传递到脚本文件,可以通过 process.argv 接收参数,代码如下

// misc/checkLog.js
/* eslint-env node */
const fs = require("fs");

const files = process.argv.slice(2); // 从第二次参数开始都是文件名

files.forEach((filePath) => {
  if (filePath.includes("/misc/")) return;
  const oldText = fs.readFileSync(filePath, "utf-8");
  const newText = oldText
    .replace(/console.log\(.*\)\n/g, "\n")
    .replace(/debugger\n/g, "\n");
  fs.writeFileSync(filePath, newText, "utf-8");
});

总结:使用husky来简化git hooks。使用lint-staged只处理暂存区的文件,并自动重新git add。使用 @commitlint/cli 来规范提交到commit-msg。使用自定义的脚本文件在代码提交前删除调试debugger 和 console.log。