在Husky的commit-msg钩子中执行git add为何无法更新提交文件?
问题分析与解决方案
核心原因
你遇到的问题本质是Git钩子的触发时机限制:commit-msg钩子是在Git已经完成暂存区快照、即将生成提交对象时触发的。此时执行git add只能把更新后的version.json放到下一次提交的暂存区,无法修改当前正在创建的提交——这就是为什么提交里是旧版本,提交后新版本才处于暂存状态。
可行解决方案
方案1:改用prepare-commit-msg钩子(推荐)
prepare-commit-msg钩子的触发时机更早:在Git生成提交消息之后、提交最终确认之前(用-m直接提交时,消息已写入COMMIT_EDITMSG;用编辑器输入时,会在编辑器启动前触发模板生成)。此时修改文件并执行git add,能将变更包含到当前提交中。
操作步骤:
- 创建
.husky/prepare-commit-msg钩子文件:
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" # $1为提交消息文件路径,与commit-msg钩子参数一致 npm run auto-version $1 && git add version.json
- 给钩子添加执行权限:
chmod +x .husky/prepare-commit-msg
- 兼容编辑器输入场景(可选):
如果用户习惯用编辑器输入提交消息,prepare-commit-msg会在编辑器启动前触发,此时COMMIT_EDITMSG是Git生成的模板而非用户最终消息。可以修改auto-version.js开头,只在直接提交(-m参数)或amend提交时执行版本更新:
// 在auto-version.js顶部添加 const commitType = process.argv[3]; // 仅处理直接提交或amend场景 if (!['message', 'commit'].includes(commitType)) { process.exit(); }
方案2:在commit-msg钩子中用git commit --amend补提交
如果不想更换钩子,可以在版本更新后,用amend命令将新版本文件追加到当前提交中,同时需要避免钩子无限循环(amend会再次触发commit-msg)。
修改.husky/commit-msg:
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" # 标记是否为amend触发,防止循环 if [ -z "$AMENDING" ]; then export AMENDING=1 npm run auto-version $1 && git add version.json && git commit --amend --no-edit fi
注意:此方式会修改提交历史,建议将
git add --all改为git add version.json,避免意外提交其他未暂存文件。
额外优化建议
- 把
auto-version.js中的版本更新逻辑和提交消息验证逻辑合并,无需单独保留commit-msg钩子做重复验证。 - 保留
pre-commit钩子的lint、格式化流程,与版本更新逻辑分离,职责更清晰。
内容的提问来源于stack exchange,提问作者Paradoxdotexe
相关产品推荐
相关产品推荐

