git - 如何确保我的 git 预提交脚本不会被愚弄?
问题描述
我正在编写一个 git 预提交脚本,并在此过程中遇到了一些困难。我遇到的第一个是将文件添加到索引后所做的更改。例如 :
- 我写了一个小
test.py
脚本 - 我使用将它添加到索引中
git add test.py
- 我改变了一些东西
test.py
(但不要git add
那些改变) - 我提交之前添加的文件
然后它触发我的预提交脚本,该脚本恰好被读取test.py
以确保它没有任何问题。问题是,即将提交test.py
的和我工作树中的那个是不同的!所以我的脚本基本上是在检查错误的文件,可能会遗漏一些非常重要的代码问题。经过一番研究,我发现有些人git stash push
在钩子的开头做了 a git stash pop
,在结尾做了 a ,以“确保”预提交脚本正在分析文件的提交版本,但我发现它是有点冒险(见下文为什么我这么认为)而且我真的不喜欢在运行由 git 命令触发的脚本时执行 git 命令的想法。所以我的第一个问题是:确保我正在分析正在提交的文件而不是我工作树中的文件的最佳方法是什么?也许我可以尝试.git/objects/*
直接读取文件?
那 git stash 的东西让我想知道......如果我公司的开发人员使用我的预提交脚本决定在预提交脚本运行时在另一个终端中切换分支怎么办?好吧,我已经知道了答案,因为我做了一些测试:提交将失败,fatal: cannot lock ref 'HEAD'
并且git stash pop
将发生在另一个分支中,并且可能会导致冲突。另一种情况可能是开发人员在存储推送之后和我的预提交脚本加载文件之前修改了文件,导致我的脚本再次分析错误的文件内容,这基本上是人类的竞争条件涉及。我确实意识到这些场景有点扭曲,但我公司的开发人员并不都熟悉 git,我绝对觉得这可能会发生......所以我的第二个问题是:即使开发人员在此期间做了一些疯狂的事情,我如何确保工作树在我的预提交完成后保持完整?我希望 git 会在钩子期间创建某种锁定文件,以防止开发人员做奇怪的事情,但它似乎没有。
我想如果有一个好方法来回答我的第一个问题,第二个问题是无关紧要的,但我还是问了它以防万一。迫不及待地想阅读你们要说的!
解决方案
然后它触发我的预提交脚本,该脚本恰好读取了 test.py 以确保它没有任何问题。问题是,即将提交的 test.py 和我工作树中的 test.py 是不同的!
这就是为什么你需要确保你的pre-commit
脚本在索引中的文件上运行,而不是在你的工作树上。实际上,分阶段提交与工作树中的实际内容不同是很常见的(例如,考虑一下,git add -p
它允许您暂存文件的一部分)。
处理此问题的一种方法是将索引签出到临时目录并在那里运行您的测试。您可以使用该git checkout-index
命令将索引的副本检出到临时目录中。
这是一个示例pre-commit
钩子,如果任何文件包含单词,它将拒绝提交BAD
:
#!/bin/sh
echo "running checks"
# create a temporary directory
tmpdir=$(mktemp -d precommitXXXXXX)
# make sure we clean it up when we're done
trap "rm -rf $tmpdir" EXIT
# check out the index
git checkout-index --prefix=$tmpdir/ -af
# run tests in a subshell so that we end up back in the current
# directory when everything finishes.
(
cd $tmpdir
if grep -q BAD *; then
echo "ERROR: found bad files"
exit 1
fi
)
我相信这也解决了您关于确保您正在测试的树在测试期间保持一致的第二个问题。因为在这里您正在使用存储库副本的临时目录中工作,所以您无需担心任何更改。
推荐阅读
- python - 从python中的字符串中删除数字
- android - 使用带有 android 的 sheet api 添加一行
- java - TelephonyManager getstate() 在 android 中返回零
- python - python 正则表达式试图匹配字符串中第二次出现的一组单词
- php - PHP 使用 FWRITE 和 SSH2 上传多个文件
- bash - 按名称显示文件的内容
- python - 如何在z之后增加字母字符而不获取特殊字符?
- python - 在 Jupyter Notebook Python 3.7.1 中执行函数后变量被更改
- typescript - 如何在 Angular 应用程序中使用 gltf-validator 包
- c# - 如何为方法 MongoDB.Bson.Serialization.BsonSerializer.Deserialize 自定义映射字段名称或类型