想象你是新上任的办公大楼物业主管。大楼每天有数百人进出——员工、访客、快递员,如果门口不设安检,谁都可以混进机房;如果安检只查工牌不查背包,危险品也能被带进去。代码仓库就是一座“代码大楼”,Git Hooks 就是安装在每个门口的自动安检门。当你执行 git commit、git push 这些动作时,它会在闸机开启前先跑一遍预设的检查脚本:代码格式对不对、测试过没过、提交信息规不规范。检查通过,闸机放行;检查失败,红灯亮起,提交被拦下。客户端钩子是你家门口的安检,服务端钩子是中央机房的安保,husky 则是一家把散装安保统一成正规军的保安公司。这篇文章,我们就从“装门禁”开始,一步步给代码大楼配齐一整套自动安检系统。

岗位关联

掌握 Git Hooks,你就能把代码规范检查、自动化测试、提交信息校验这些重复劳动凝结成团队制度,让每一次代码进出仓库都自动经过质量安检——这是从独立开发者走向工程化团队协作的必备技能。

目录
  1. 可视化演示
  2. 钩子入门:认识代码大楼的门禁系统
  3. 客户端钩子:家门口的三道安检
  4. 服务端钩子:中央机房的最后防线
  5. 脚本编写:给安检员写执勤手册
  6. 自动化实践:让安检自动运转
  7. 钩子统一配置:用 husky 组建安保团队
  8. 实战配置:从零布置一套完整体检
  9. 调试排障:安检出错之后的求生指南
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示pre-commit、commit-msg、pre-push等Git钩子如何在代码提交各阶段自动执行检查与验证。

本节配有交互动效(进入视口后自动加载,约 3KB)。

pre-commit检查 代码格式化与lint检查 单元测试执行 提交前自动拦截问题代码

钩子入门:认识代码大楼的门禁系统

作为物业主管,你要先搞清楚地盘上有哪些“门”。Git 仓库不是一座孤楼,它分“本地办公区”和“中央机房”两个区域。你在本地敲 git commit,相当于带着一份材料进自己的办公室;git push,则是把材料递送到中央机房的档案柜。Git Hooks 就是嵌在每道门上的一排感应盒子,事件一发生,盒子里的脚本就会被自动触发。

Git Hooks 官方叫法叫“钩子”,本质是 Git 在特定事件发生时执行用户自定义脚本的机制。它们存放在每个仓库的 .git/hooks 目录下,文件名就是触发事件名,比如 pre-commit、commit-msg。Git 初始化仓库时会生成一批 .sample 示例文件,把它们改名为不带后缀的正式文件名、写入脚本,钩子就激活了。一个钩子可以对应任何类型的脚本文件,只要系统能执行它。

钩子的触发时机覆盖了 Git 操作的生命周期。一次提交要依次经过 pre-commit(提交前检查)、prepare-commit-msg(准备提交信息)、commit-msg(校验提交信息)、post-commit(提交后通知);一次推送会触发本地的 pre-push,再到服务端的 pre-receive、update、post-receive。客户端钩子只管你本地这一亩三分地,服务端钩子则由中央仓库管理员部署,对所有协作成员生效。

所以作为物业主管,你先要画一张“门禁地图”:哪些门归自己管,哪些门归中央机房管。地图画明白了,才能给每个岗位安排合适的安检员。

客户端钩子:家门口的三道安检

你所在楼层的办公区有三个安检口:进办公室查材料(pre-commit)、填出入登记表校验格式(commit-msg)、离开办公室送材料去中庭时再查一遍(pre-push)。三道安检各管一件事,任何一道亮红灯,你的这次“出行”都会被拦下。

pre-commit 是最常用的钩子,它在 git commit 输入提交信息之前执行,适合做代码规范检查、静态分析、检查是否遗留调试代码。commit-msg 钩子会收到一个参数——存放提交信息的临时文件路径,它读取内容并按正则校验,比如要求格式为 feat: 增加登录功能。pre-push 则在 git push 时触发,在远端连接建立后、引用更新前运行,适合跑全量测试和构建验证。post-commit 在提交成功后触发,常用于发送通知或生成文档。

这些钩子最终通过一个退出码向 Git 汇报结果。如果用逻辑表达式描述,pre-commit 的判定可以写成:

客户端钩子最大的弱点是“信任本地”——每个团队成员电脑上的钩子版本可能不一致,有人甚至不装。这正是后面 husky 登场的理由:把散装安检统一成正规军。

exit={0,lint 与 test 全部通过1,任一检查失败\displaystyle \text{exit} = \begin{cases} 0, & \text{lint 与 test 全部通过}\\ 1, & \text{任一检查失败}\end{cases}
退出码是 Git 与脚本之间唯一的“对话语言”:0 表示放行,非 0 表示拦截。这个约定贯穿所有钩子。
  1. 检查串联pre-commit 脚本把代码规范检查和单元测试串成一条流水线,先跑 lint 再跑 test,两项缺一不可。
    lint∧test\text{lint} \land \text{test}
  2. 成功出口两项检查都通过,脚本返回退出码 0,相当于安检员在你的出入证上盖了一个“验讫”章,闸机放行。
    exit=0\text{exit} = 0
  3. 失败拦截只要有一项检查失败,脚本返回退出码 1,Git 立刻中止提交,并把你拦在门外打印错误原因。
    exit=1\text{exit} = 1

服务端钩子:中央机房的最后防线

本地安检再严格,也防不住有人绕过它直接往中央机房塞材料。中央机房的安保才是真正的最后一道闸——它的名字叫“服务端钩子”。

服务端钩子部署在远程仓库(比如 GitHub、GitLab 或自建 Git 服务器)里,对每个推送执行审查。pre-receive 在引用更新前触发,能看到整个推送包含的所有提交,适合做整体合规检查;update 对每个即将更新的分支各触发一次,可以逐分支设置规则;post-receive 在更新完成后触发,常用于自动部署或发送通知。

权限控制是服务端钩子的经典场景。一个推送能否被接受,可以抽象成三个条件的交集:

中央安保的眼睛能看全整个批次的材料,这是本地安检做不到的。也正因如此,服务端钩子是团队规范“不可绕过”的底线。

allow=(author∈Rteam)∧(branch∈Bprotected)∧(lint_ok=true)\displaystyle \text{allow} = (\text{author} \in R_{\text{team}}) \land (\text{branch} \in B_{\text{protected}}) \land (\text{lint\_ok} = \text{true})
这个公式的意思是:推送者得在团队成员名单里,推送的目标分支得符合保护策略,推送的代码还得通过服务端的质量检查。三个条件同时成立才放行。
  1. 作者校验先看推送者是否在团队成员白名单 R_team 中,防止陌生人直接向中央仓库写入代码。
    author∈Rteam\text{author} \in R_{\text{team}}
  2. 分支校验再看推送的目标分支是否属于受保护分支集合 B_protected,比如 main 分支禁止普通成员直接推入。
    branch∈Bprotected\text{branch} \in B_{\text{protected}}
  3. 代码检查服务端再次运行代码检查,确认本地检查没被跳过、也没有被 --no-verify 绕过。
    lint_ok=true\text{lint\_ok} = \text{true}
  4. 综合判定三个条件用逻辑与(∧)连接,任何一个不满足,allow 就是假,整个推送被拒绝。
    allow=true\text{allow} = \text{true}

脚本编写:给安检员写执勤手册

安检员的执勤手册不规定必须用哪种语言写,但工作内容和汇报方式必须写清楚。Git 对钩子脚本的语言选择非常宽容——Shell、Python、Node.js 都可以,只要系统能找到解释器。脚本放在 .git/hooks/<hook-name>,还需要赋予可执行权限。

脚本通过退出码和 Git 对话:退出码 0 表示放行,其他任意非零值表示拦截。脚本还可以通过标准输出向用户打印拦截原因,比如“第 3 个 Python 文件有语法错误”。如果脚本在 Windows 上运行,还要注意换行符和 shebang 的兼容性,#!/bin/sh 这类声明放在文件第一行。

钩子执行时的环境变量也需要留意。Git 会设置 GIT_DIR 指向仓库的 .git 目录,还会传入事件相关的参数,比如 commit-msg 钩子收到的第一个参数就是提交信息文件的路径。脚本里如果需要读取仓库文件,最好使用绝对路径或基于 GIT_DIR 的相对路径,避免被当前工作目录干扰。

手册写得再漂亮,保安看不懂(没有执行权限)或找不到人(解释器不存在),门禁也是一堆废铁。所以写完脚本,第一件事是 chmod +x,第二件事是手动跑一遍。

自动化实践:让安检自动运转

安检值岗最怕机械重复。让脚本自动扫描、自动测试,才称得上“智能门禁”。代码规范检查是最常见的自动化场景——前端项目用 ESLint 加 Prettier,Python 项目用 ruff 或 black,在 pre-commit 里对暂存区文件扫一遍,风格问题当场修复。

自动测试则放在 pre-push 或 CI 中运行全量套件,因为每次 commit 都跑全部测试会拖慢节奏,而推送前跑一遍是性价比最高的时机。文件变更检查是进阶技巧:只对改动涉及的文件类型做对应检查,比如改了 Python 文件才做语法编译检查,改了 Markdown 才检查链接是否失效。

提交信息校验是另一大自动化阵地。commit-msg 钩子读取提交信息文件,用正则校验格式。工业界通行的 Conventional Commits 规范,简化后可以用一个模板描述:

这样门禁不仅会拦人,还能自动辨别该查背包还是查证件——不同文件类型、不同提交类型,走各自的检查通道。

(feat∣fix∣docs∣style∣refactor∣test∣chore)⏟类型([a−z]+)?⏟可选范围:.{1,50}⏟描述长度\displaystyle\underbrace{(feat|fix|docs|style|refactor|test|chore)}_{\text{类型}}\underbrace{([a-z]+)?}_{\text{可选范围}}: \underbrace{.\{1,50\}}_{\text{描述长度}}
这个模板规定了提交信息必须像写卡片一样格式化:先说清楚“这次改动属于什么类型”,再说影响范围,最后用一句短描述收尾。
  1. 类型限定提交信息必须以七个关键词之一开头,表明这次改动是加功能、修 bug 还是写文档。
    (feat∣fix∣docs∣style∣refactor∣test∣chore)⏟类型\underbrace{(feat|fix|docs|style|refactor|test|chore)}_{\text{类型}}
  2. 可选范围括号里的 scope 表示影响的具体模块,例如 fix(login): 修复登录超时,也可以省略不写。
    ([a−z]+)?⏟可选范围\underbrace{([a-z]+)?}_{\text{可选范围}}
  3. 冒号与空格类型与描述之间用英文冒号加空格分隔,统一格式才能让 commit-msg 钩子稳定解析。
    : \text{: }
  4. 描述长度描述部分限制为 1 到 50 个字符,太短说不清改动意图,太长则容易变成流水账。
    .{1,50}⏟描述长度\underbrace{.\{1,50\}}_{\text{描述长度}}

钩子统一配置:用 husky 组建安保团队

要把十几个楼层的安检标准统一,靠口头通知是不行的。你得发制服、配统一的检查手册,并且让新员工入职第一天就领到。husky 就是这样一个“保安公司”——它把钩子配置写进 package.json,安装时自动在 .git/hooks 创建关联脚本,让钩子配置随代码仓库一起共享。

husky 的典型搭档是 lint-staged。lint-staged 只对暂存区中的文件运行检查,避免每次提交都全量扫描整个项目。在 package.json 中可以这样配置:

husky 较新版本使用 npx husky init 初始化,生成 .husky/pre-commit 文件。团队其他人克隆仓库后,只需运行 npm install,钩子就自动激活。这样“换台电脑钩子就没了”的痛点彻底消失,每个新同事拆开电脑的那一刻,就已经穿着统一的制服上岗。

json3 行
"lint-staged": {  "*.js": ["eslint --fix", "prettier --write"]}

实战配置:从零布置一套完整体检

今天是新人入职第一天,我们跟着他走一遍完整的布岗流程。以一个 Python + 前端混合项目为例,完整配置分为四步:初始化仓库并安装依赖;初始化 husky 生成 .husky 目录;编写 pre-commit 钩子调用 lint-staged 做格式化与语法检查;配置 commit-msg 钩子调用 commitlint 校验提交信息。

具体到 Python 部分,pre-commit 钩子可以写成检查暂存区 .py 文件能否通过编译、是否存在行尾多余空白——这正是后面 Python 演示代码做的事。前端部分则在 lint-staged 中对 .js 和 .ts 文件运行 ESLint。提交信息规则配置在 commitlint.config.js 中,类型限定为 feat/fix/docs 等关键词。

配置完成后,用一次真实的提交做“消防演习”:故意写一个错误格式的提交信息,看 commit-msg 钩子是否拦截;故意在代码里留语法错误,看 pre-commit 是否报警。两道关卡都拦住了,这套安检系统才算真正上线。布岗完成后的第一次演习,让我们对这套系统的可靠性有了信心。

调试排障:安检出错之后的求生指南

再好的安检系统也会遇到报警器误响或门禁失灵,物业主管要学会快速排查。钩子不生效最常见的三个原因是:文件名带了 .sample 后缀没去掉、脚本没有可执行权限(需要 chmod +x)、shebang 指向的解释器不存在。排查时可以先在终端手动执行脚本看报错,再运行 git commit -v 查看详细输出。

绕过机制也需要了解:git commit --no-verify 可以跳过 pre-commit 和 commit-msg,git push --no-verify 可以跳过 pre-push——但它们都绕不过服务端钩子。因此团队规范要靠服务端兜底,而不是指望每个人都自觉。

日志排查方面,可以在钩子脚本里加 echo 输出调试信息,配合 GIT_TRACE=1 环境变量查看 Git 调用钩子的完整过程。团队协作还要注意:客户端钩子版本不一致时,要求全员更新 husky 配置并重新 install;每个钩子只做一件事,职责单一才容易调试。门禁偶尔虚惊一场不可怕,可怕的是不知道哪扇门在响、响过之后该找谁。

AI 应用场景

AI 代码审查自动门禁

阶段:代码质量门禁(CI/CD 自动化)

解决的问题:人工 code review 滞后、审查标准因人而异。传统做法靠 reviewer 肉眼检查 diff,效率低且容易漏掉安全隐患。在服务端钩子或 CI 流程中接入 AI 代码审查工具(如 CodeRabbit),每次推送自动触发 AI 对代码差异做安全性、性能和风格审查,并在合并请求上生成评论。

具体案例:某中型团队在 GitLab CI 的 pipeline 中集成 AI 审查服务,合并请求时 AI 先过一遍代码,自动标记明显的 bug 与安全漏洞,人工 reviewer 只需聚焦 AI 标记的高风险片段,评审时间缩短了一半。

AI 提交信息生成助手

阶段:提交信息生成

解决的问题:开发者提交信息随意、格式混乱,难以追溯需求变更。传统方案靠 commit-msg 钩子硬性拦截,但开发者经常不知道怎么描述。改进方案是在钩子流程中调用本地 LLM:把暂存区 diff 摘要发给模型,自动生成符合 Conventional Commits 规范的提交信息,供开发者确认后使用。

具体案例:某团队在 pre-commit 钩子里接入 OpenAI API,先把暂存区 diff 截断到数千 token,让模型总结成中英文对照的提交信息写入提交信息文件,随后 commit-msg 钩子再校验格式是否合规,形成“AI 写、钩子查”的双保险。

AI 团队规范效能教练

阶段:数据反馈与持续改进

解决的问题:规范落地后没人统计执行效果,团队规范容易流于形式。利用 post-receive 钩子把每次推送的提交信息、检查结果汇总到日志平台,AI 助教定期分析团队提交习惯,输出改进建议。

具体案例:某公司用 post-receive 钩子把 push 事件写入 ClickHouse,每周由 AI 生成“规范体检报告”,指出哪类提交信息最常被打回、哪个模块的测试最薄弱,帮助研发效能团队精准改进流程。

Python 演示

python59 行
#!/usr/bin/env python3"""pre-commit 钩子: 检查暂存区 Python 文件语法与行尾空白. """ import subprocessimport sys PYTHON_EXT = '.py'CHECKED_EXTS = ('.py', '.js', '.ts', '.json', '.md')  def get_staged_files():    """返回暂存区中新增/修改/重命名的文件列表. """    result = subprocess.run(        ['git', 'diff', '--cached', '--name-only', '--diff-filter=ACM'],        capture_output=True, text=True, check=True    )    return [line.strip() for line in result.stdout.splitlines() if line.strip()]  def check_python_syntax(path):    """用 Python 编译器检查语法, 有错误会抛 SyntaxError. """    with open(path, encoding='utf-8') as fh:        source = fh.read()    compile(source, path, 'exec')  # 语法检查    return True  def check_trailing_whitespace(path):    """检查文件是否存在行尾多余空白. """    with open(path, encoding='utf-8') as fh:        lines = fh.readlines()    return [(i + 1, line) for i, line in enumerate(lines)            if line.endswith(' \n') or line.endswith('\t\n')]  def main():    staged = get_staged_files()    errors = []    for path in staged:        if path.endswith(PYTHON_EXT):            try:                check_python_syntax(path)            except SyntaxError as exc:                errors.append(f'{path}: 语法错误 -> {exc}')        if path.endswith(CHECKED_EXTS):            bad = check_trailing_whitespace(path)            for lineno, _ in bad:                errors.append(f'{path}:{lineno}: 行尾有多余空白')    if errors:        print('提交被拦截, 请修复以下问题:')        for err in errors:            print('  -', err)        sys.exit(1)    print('检查通过, 可以提交')    sys.exit(0)  if __name__ == '__main__':    main()
目的:这是一个可直接放进 .git/hooks/pre-commit 的 Python 脚本,它会自动获取暂存区文件列表,对 .py 文件做语法编译检查,对所有常见文本文件做行尾空白检查,任何问题都会导致提交被拦截。
  1. ['git', 'diff', '--cached', '--name-only', '--diff-filter=ACM']这一行通过给 Git 下达“列出暂存区里新增、修改、重命名的文件”命令,拿到需要检查的文件清单
  2. capture_output=True, text=True, check=True让 Python 捕获命令输出并转成文本,命令执行失败时直接抛异常,避免脚本静默出错
  3. compile(source, path, 'exec')调用 Python 编译器对源码做语法检查,不生成字节码文件,只验证“能不能编译通过”
  4. errors.append(f'{path}:{lineno}: 行尾有多余空白')把每个问题累积到错误列表,所有检查结束后一次性打印,方便开发者统一修复
  5. sys.exit(1)用非零退出码告诉 Git 拦截本次提交,这正是钩子与 Git 之间的“红灯信号”

常见误区

误区我明明把脚本放在 `.git/hooks` 目录里了,怎么 commit 的时候完全没有反应?是不是 Git 版本太旧不支持?

正解大概率是脚本没有可执行权限,或者文件名带了 .sample 后缀没去掉。Git 只会执行有 x 权限、且文件名称严格匹配事件名的脚本。运行 ls -l .git/hooks/pre-commit 看看权限位,必要时执行 chmod +x .git/hooks/pre-commit。就像安检员没穿上制服站在岗位上,闸机当然不会认出他。

为何常见:教程和文档只强调“放在 hooks 目录”,初学者容易忽略 Unix 的权限模型,以为文件放对位置就够了。

误区我把 pre-commit 钩子配好了,以后团队每个人都会自动执行同一套检查,我就可以放心了。

正解.git/hooks 是本地目录,不会被 clone 或 push 共享。要把钩子带到团队,必须用 husky 这类工具把配置写进版本库,成员拉取代码后运行安装命令自动激活。否则就像只在你的工位装了摄像头,同事那边还是“裸奔”状态。

为何常见:把“本机生效”误当成“项目级生效”,混淆了本地配置和团队配置的边界。

误区既然有人能用 `git commit --no-verify` 跳过 pre-commit,那钩子检查根本没有意义,防不住想偷懒的人。

正解--no-verify 只能跳过客户端钩子,服务端 pre-receive 钩子部署在中央仓库,本地用户根本无法控制。团队规范真正可靠的兜底在服务端,客户端钩子只是第一道便捷的过滤器。

为何常见:只接触过本地仓库的开发者容易高估 --no-verify 的权限范围,不知道服务端还有一道无法绕过的闸机。

误区钩子检查会把整个项目的测试都跑一遍,项目一大每次提交都要等好几分钟,不如直接关掉钩子。

正解钩子粒度可以精细控制。lint-staged 只对暂存区改动的文件运行检查,全量测试放到 pre-push 或 CI 上跑。就像机场安检不会把整个候机楼重新排查一遍,只检查眼前的行李。

为何常见:没有理解不同钩子适合不同强度的检查,把 pre-commit 和 pre-push 的职责混为一谈。

面试题

Q1. Git Hooks 脚本默认存放在哪里?

单选题 · easy

  • A..git/hooks 目录中← 正确答案
  • B..git/config 目录
  • C.hooks/config 目录
  • D..hooks 目录里面

答案:A。Git Hooks 默认存放在每个仓库的 .git/hooks 目录下,文件名与事件名一致。.git/config 存放仓库配置,hooks/config 和 .hooks 都不是 Git 约定的目录。就像大楼的安检设备统一安装在门禁控制室,而不是随便放在某个办公室。

Q2. pre-commit 钩子在哪个时机执行?

单选题 · easy

  • A.当 git commit 命令执行前← 正确答案
  • B.当 git push 命令完成前
  • C.当 git merge 结束之前
  • D.当 git clone 执行之前

答案:A。pre-commit 在 git commit 弹出提交信息编辑窗口之前执行,适合做代码规范检查。push 之前对应的是 pre-push 钩子,merge 和 clone 没有 pre-commit 这个环节。安检发生在你进门之前,而不是坐进办公室之后。

Q3. 钩子脚本返回非零退出码会发生什么?

单选题 · mid

  • A.中断本次提交并回滚← 正确答案
  • B.提交照常继续执行
  • C.静默警告然后放行
  • D.自动删除暂存区里文件

答案:A。非零退出码表示检查失败,Git 会中止当前操作,但不会自动回滚或删除文件,暂存区内容保持原样。这相当于安检红灯亮起,门禁关闭,但不会没收你的行李。选择 B、C 与钩子的设计目的相悖,D 是错误推断。

Q4. commit-msg 钩子收到的第一个参数是什么?

单选题 · mid

  • A.提交的完整信息文本
  • B.提交信息文件路径← 正确答案
  • C.本次提交哈希值
  • D.提交作者的用户名

答案:B。commit-msg 钩子的第一个参数是存放提交信息的临时文件路径,脚本需要读取该文件内容来校验格式。哈希值在提交完成后才生成,作者信息也在提交时写入,二者都不可能提前传给钩子。这个参数就像给安检员的登记表存放地址,而不是登记表本身。

Q5. husky 工具解决的核心问题是什么?

单选题 · mid

  • A.提高钩子脚本的执行速度
  • B.让钩子入库并团队共享← 正确答案
  • C.把脚本翻译成中文
  • D.自动修复代码的规范问题

答案:B。husky 的核心价值是把钩子配置纳入版本库管理,团队成员 clone 后只需安装依赖就能自动激活钩子,解决了 .git/hooks 不随仓库分发的问题。它不提升脚本执行速度,也不负责翻译和自动修复代码,那些是 lint-staged 等工具配合完成的。

Q6. pre-receive 与 update 钩子的主要区别是什么?

单选题 · hard

  • A.pre-receive 看全部推送,update 是逐分支← 正确答案
  • B.update 看全部推送,pre-receive 只查分支
  • C.pre-receive 与 update 效果完全相同
  • D.pre-receive 只在首次推送时触发一次

答案:A。pre-receive 在整个推送操作开始前触发一次,能看到本次推送涉及的全部提交;update 对每个即将更新的分支各触发一次,适合对不同分支应用不同规则。就好比总安检官先看整批货物的清单,各楼层安检员再逐车厢细查,二者分工不同。

Q7. 如何强制团队成员执行提交规范?

单选题 · mid

  • A.配置强制的客户端 pre-commit 检查
  • B.在服务端部署 pre-receive 钩子← 正确答案
  • C.在 README 中写明规范并提醒
  • D.要求每个人提交时自觉遵守规范

答案:B。客户端钩子可以被 --no-verify 跳过,README 和自觉性也不具备强制力。只有服务端 pre-receive 钩子部署在中央仓库,提交者无法绕过,才能实现“强制”执行。这是团队规范的最后一道物理闸门。

Q8. 以下哪些属于客户端钩子?

多选题 · mid

  • A.pre-commit 钩子← 正确答案
  • B.commit-msg 钩子← 正确答案
  • C.pre-receive 钩子
  • D.post-commit 钩子← 正确答案

答案:ABD。pre-commit、commit-msg、post-commit 都在本地仓库执行,属于客户端钩子。pre-receive 部署在服务端中央仓库,属于服务端钩子。客户端钩子管“本地进门”,服务端钩子管“中央机房验收”。

Q9. 关于 --no-verify 参数的说法正确的是?

多选题 · mid

  • A.只能跳过客户端本地钩子← 正确答案
  • B.可以跳过服务端强制钩子
  • C.跳过 pre-commit 的规范检查← 正确答案
  • D.服务端钩子无法用参数跳过← 正确答案

答案:ACD。--no-verify 只能跳过客户端钩子(如 pre-commit、commit-msg、pre-push),对服务端 pre-receive 钩子无效。所以客户端检查可以被绕过,但服务端兜底依然生效。选 B 的人混淆了本地参数与服务端部署的区别。

Q10. 关于服务端钩子的说法正确的是?

多选题 · hard

  • A.部署在每个人的本地仓库
  • B.在中央服务器统一执行← 正确答案
  • C.可作为团队规范的最终防线← 正确答案
  • D.能强制拦截不合规的推送← 正确答案

答案:BCD。服务端钩子部署在中央服务器仓库,由仓库管理员维护,对所有推送者生效。因为不受开发者本地环境控制,所以能充当团队规范的最终防线并强制拦截不合规推送。选项 A 是客户端钩子的特征,张冠李戴了。