likes
comments
collection
share

你应该知道的 githooks

作者站长头像
站长
· 阅读数 10

前言

现代web开发中,多人合作项目已经是常态。在此场景下,为了提升合作效率和质量,减少因个人习惯分歧而导致的额外成本,标准化规范化的需求自然浮现出来,代码规范,commit 规范等等,以保证在项目创建、开发、部署等阶段有序可循。如果上述规范仅仅是停留在文档阶段靠人的自觉性,落地自然遥遥无期,因此各种工具又被召唤出来,进行工程化的保障,例如搭配不同技术栈的各种cli,vuecli,cra等等。 本文聚焦在git 交互阶段,探究下如何卡控git相关阶段。

栗子

pre-commit配置不生效

我们团队的同学,基于vue-cli +自定义了一些扩展,形成了内部通用的脚手架,但在创建空模板项目时候,却发现了 配置不生效的bug。 出现步骤如下:

  1. cli 创建空白项目,会进行模板生成,依赖安装等行为
  2. git init 进行初始化
  3. 变更提交相关信息,期望执行pre-commit 回调。
"gitHooks": {
    "pre-commit": "lint-staged"
 }

结果 毫无反应。

怪异表现: npm重装lint相关依赖后可以生效

排查思路

大兄弟判断是对应版本不正确,试了n多版本,依然是上面那个表现。

找到我一起看,听过他的描述之后,那就先控制变量,排除lint相关依赖的干扰。 先关注pre-commit这个hooks到底执行没有,修改对应脚本如下:

"gitHooks": {
    "pre-commit": "echo '>>>>>1111111>>>>>'"
 }
  1. 如果有对应输出 说明确实lint相关组件问题
  2. 如果没有,那就去关注githook为何没有执行

修改之后,果然 没有 111出现,说明githook 没有唤起。 一番搜索之后,毫无相关头绪,没办法 只能去翻翻githook官方文档了。

gitHook 原理

githooks官方文档有比较清晰的说明,这里就不全篇展开了。

简而言之,客户端(即我们开发者本地)进行commit等操作时,会触发pre-commit,commit-msg等钩子,这些钩子对应的执行文件,大多数存放于.git/hooks,git init的时候会初始化一些xxx.sample文件进行填充,这些文件并不会执行,他们只是示例文件而已,告诉大家如何写合规的脚本文件。把一个正确命名且可执行的文件放入 Git 目录下的hooks子目录中,可以激活该挂钩脚本

注意上面的粗体部分,要想一个hook可用,必须要有已被编辑过的文件存在.git/hooks,如果仅仅是pre-commit.sample这种,git判断没有自定义操作,所以不会执行对应指令。

举个例子,pre-commit.sample的内容如下:

# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments.  The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".

告诉大家怎么写正确的指令文件,本身并没有逻辑。

问题定位& 解决

回到我们的问题,直接查看下 .git/hooks 下面果然只有pre-commit.sample 文件,自然没有执行。 重装依赖后 查看,pre-commit文件就存在了,自然命令就生效了。 直接导致的原因,回到我们上方

  • 先安装依赖,此时并没有git init,自然就缺少.git/hooks 目录,创建脚本文件失败了。
  • 重装的时候,此时可以找到正确的文件目录,文件创建成功,自然脚本也生效

依赖上方推断,lint-staged 在install的时候应该有创建pre-commit的动作。 不过lint-staged 依赖husky,逻辑比较分散,代码就不贴了,想要了解的同学可以看下husky的index.ts&& .husky: 创建了两个文件: pre-commit && ## commit-msg

有个更清晰一点的,可以一眼看出来做了啥: pre-commit

//  这就是创建对应hoos文件了
try { fs.writeFileSync(precommit, precommitContent); }
catch (e) {
  console.error('pre-commit:');
  console.error('pre-commit: Failed to create the hook file in your .git/hooks folder because:');
  console.error('pre-commit: '+ e.message);
  console.error('pre-commit: The hook was not installed.');
  console.error('pre-commit:');
}

结束语

到这里,借用上面那个栗子,githook相关的内容就理的差不多了,以上内容抛砖引玉,希望一起学习进步知自然也知其所以然,

参考文章: