3.3 dsh-pre-push-checks:推送前的最后一道关

它是什么

dsh-pre-push-checks 的官方描述:在推送、强推、标记为待评审或合并之前使用。

约 11283 字节,覆盖四个动作前的检查。这四个动作有个共同点:一旦做了,就很难不动声色地收回。 推送会把代码送到远端,强推会改写他人可能已经拉取的历史,标记待评审等于邀请别人为你的代码花时间,合并则直接进入主干。技能把检查点卡在这四个动作之前,本质上是在保护“还能安静改错”的那个窗口。

为什么卡在 push 之前

研发流程里有个经验规律:问题发现得越晚,修复成本越高。

阶段 发现问题 修复成本
本地编辑 自己改 分钟级
commit 后 amend 或新 commit 十分钟级
push 后 强推,可能影响他人 小时级 + 协作成本
合并后 需要 revert + 回归 天级

注意这张表里最陡的一跳是从“本地”到“push 后”:成本从十分钟级跳到小时级,多出来的不是修复时间,是协作成本——你要通知所有人重新拉取,别人基于旧历史的提交要收拾。第二跳是合并后,修复动作从“改代码”变成“回滚 + 回归 + 重新发版”,牵动面再上一个量级。

dsh-pre-push-checks 存在的意义就是把检查点尽量往前挪,在“还很容易改”的时刻把问题拦下。它不替代任何流程,只是保证你在按下一个难以撤回的按钮之前,已经被同一份清单问过一遍。

它一般检查什么

按工程惯例与技能体量推断,这类推送前检查通常覆盖六个类别:

类别 典型项
构建 类型检查、编译、打包是否通过
测试 相关测试是否跑过、是否全绿
格式 代码格式、导入顺序、无用导入
提交卫生 commit message 是否清晰、是否混入无关改动
分支状态 是否落后于上游、是否需要 rebase
副作用 是否带了调试代码、console 输出、临时文件

其中“提交卫生”和“副作用”两类最容易被忽略,也最值得自动化:一个混着无关改动的 commit、一行忘记删的 console.log,靠人是查不出来的,靠清单可以。

dsh 版本还会包含它自己的钩子要求(例如特定的 lint 规则、快照测试)。

一份十项以内的推送前清单示例

和评审清单一样,这个技能的关键在于“短而真查”。下面是一份可直接改造的起点:

## 推送前检查
- [ ] 相关测试通过(只跑受影响模块)
- [ ] 类型检查 / 编译通过
- [ ] 无调试残留(console、debugger、临时开关)
- [ ] 无混入的无关改动
- [ ] commit message 能说清“为什么改”
- [ ] 分支已 rebase 到最新上游
- [ ] 公开 API 变更已写迁移说明
- [ ] 大文件 / 密钥没有进暂存区

最后一条值得单说:密钥泄露是推送前最容易酿成大祸、却最容易被忽略的项。一旦 push 到远端,即使立刻删掉,历史里也留下了。把“密钥 / 大文件未进暂存区”写进清单,比事后轮换密钥便宜一万倍。

与 CI 的分工

常见误解是“有 CI 就行了”。实际上两者定位不同:

pre-push 技能 CI
速度 快(可只跑相关部分) 慢(全量)
时机 推送前,可拦下 推送后,只能报错
反馈 交互式,可追问 日志,需自行翻
定位 省一次失败的 CI 守门,不可绕过

展开说:CI 的价值在于不可绕过——它守在远端,本地手段跳不过它;pre-push 技能的价值在于可对话——检查失败了你可以当场问“这个失败能不能放过、为什么”,而不是对着日志干瞪眼。一个在门里,一个在门外,少了哪个都漏。

正确姿势是关键项本地跑,全量交给 CI。把所有检查都堆在 CI,结果就是每个人每天都在等一次注定失败的构建。

技能 vs 钩子(hook)

有人会问:这不就是 git hook 吗?区别在三点:

维度 pre-push 技能 git hook
修改方式 改 Markdown 即可 改脚本文件,需分发
可对话性 失败可追问原因 脚本直接拒绝,信息有限
跨机一致性 随仓库走,所有人一致 依赖每人本地装了钩子

钩子的优势是“无法绕过”,劣势是僵硬、难维护、换了机器就丢。技能的优势是灵活、可读、随仓库版本化;劣势是它依赖人或模型主动调用,理论上能被跳过。实务上两者可以共存:用钩子兜底硬性红线(如密钥扫描),用技能做可对话的软性检查。

改造三要点

  1. 换命令。 把 dsh 专属命令换成你项目的(pnpm test / npm run lint 等),这是最低限度的改造,不改就用不了。
  2. 清单控制在十条以内。 超过十条没人会认真看——包括模型。十条以内的清单,每条都是真检查;五十条的清单等于没有清单。
  3. 明确哪些可放过。 提前定义“哪些失败必须拦住,哪些可以放过并说明理由”。没有这条,技能要么太松形同虚设,要么太紧被大家绕开——被绕开的检查比没有检查更糟,因为它制造了“已经查过了”的错觉。

单人项目怎么用

没有团队也值得装。单人项目的“评审人”是未来的自己:三个月后回看这个仓库,你最希望当时的自己提前拦下什么?把那个清单写进去。常见的单人痛点——忘了跑测试就推、把本地配置文件推上去、commit message 全写成“update”——都能被一份十项清单兜住。

你要不要装

你的情况 建议
有 CI 但本地常忘跑 强烈建议,把 CI 的关键项搬到本地
单人项目 建议,替代手工记忆
已有完善的 pre-commit 钩子 可选,技能比钩子更灵活但更慢

小结

  • dsh-pre-push-checks 卡在推送、强推、待评审、合并四个动作之前,约 11283 字节。
  • 核心思想:把检查点前移到修复成本最低的时刻。
  • 与 CI 互补而非替代:关键项本地,全量 CI。
  • 改造时清单控制在十条以内,并明确哪些失败可放过。

延伸阅读