如何在pre-commit钩子中验证提交后状态(支持指定文件提交)
解决pre-commit钩子中静态检查兼容指定文件提交及隔离本地修改的问题
你可以借助Git内置的stash命令,在pre-commit钩子中临时隔离未暂存、未跟踪的本地修改,仅针对将要提交的暂存区内容运行静态检查,同时完美兼容git commit -m"foo" file1 file2这类指定文件提交的场景,不需要依赖别名或共享配置。
核心思路
pre-commit钩子触发时,Git已经将要提交的变更存入暂存区。我们可以:
- 用
git stash把未暂存、未跟踪的修改临时保存,同时保留暂存区的内容(确保工作区和将要提交的状态完全一致) - 在干净的工作区(仅含暂存区内容)运行静态检查
- 检查完成后恢复之前保存的本地修改,不影响用户的工作状态
具体钩子脚本示例
创建或修改.git/hooks/pre-commit文件,写入以下内容(确保脚本有可执行权限:chmod +x .git/hooks/pre-commit):
#!/bin/sh # 临时保存未暂存、未跟踪的修改,保留暂存区内容 git stash push --quiet --keep-index --include-untracked --message "pre-commit-hook-temp-stash" # 运行静态检查命令,根据你的需求调整 # 示例:检查所有Python文件 mypy . MYPY_EXIT_CODE=$? # 仅检查将要提交的Python文件,提升效率 pylint $(git diff --cached --name-only --diff-filter=ACM | grep "\.py$") PYLINT_EXIT_CODE=$? # 恢复之前保存的本地修改 git stash pop --quiet # 若任意检查失败,终止提交 if [ $MYPY_EXIT_CODE -ne 0 ] || [ $PYLINT_EXIT_CODE -ne 0 ]; then echo "❌ 静态检查未通过,提交已终止" exit 1 fi exit 0
关键细节说明
--keep-index:保留暂存区内容,让工作区完全匹配将要提交的状态,不会丢失要检查的目标内容--include-untracked:把未跟踪文件也存入stash,避免这些文件干扰静态检查的结果--quiet:隐藏stash的默认输出,让钩子输出更简洁- 针对指定文件提交的场景:当用户使用
git commit -m"foo" file1 file2时,暂存区仅包含这些指定文件的变更,stash后工作区里的这些文件是提交版本,其他文件的修改都被临时保存,检查只会针对要提交的内容,完全兼容 - 优化检查范围:用
git diff --cached --name-only --diff-filter=ACM | grep "\.py$"可以只筛选出将要提交的Python文件,避免检查无关文件,提升效率
注意事项
- 不要在钩子脚本中修改暂存区内容,否则会改变最终提交的内容
- 如果你的静态检查工具需要读取配置文件(如
mypy.ini、.pylintrc),确保这些文件已被跟踪或在stash时不会被影响(默认已跟踪文件的未暂存修改会被stash,配置文件如果是已跟踪且未修改的话会保留在工作区)
内容的提问来源于stack exchange,提问作者frans
相关产品推荐
相关产品推荐

