Git 预提交挂钩:防止更改特定文件的提交
Git pre-commit hook: Prevent commits that change particular files
我的项目下有几个 .json 文件,其中包含多个键。这些密钥不得受版本控制。我在我的项目中用假的密钥替换了那些实际的密钥,以防止在持续集成时构建失败。
但是,开发人员需要 copy/paste 在他们的笔记本电脑上安装这些文件才能测试应用程序。
现在,问题是开发人员可能会忘记并错误地将它们提交到 git。我想要 运行 一个 pre-commit
脚本来检查修改过的文件,如果添加了其中一个文件,则提交失败。
有什么办法可以做到吗?
您可以在预提交挂钩中执行类似的操作:
FILES_PATTERN='<regexp_to_match_file_names>'
if git diff --cached --name-only | grep -qE $FILES_PATTERN; then
exit 1;
else
exit 0;
fi
这个想法基于这些参考资料:
- https://unix.stackexchange.com/questions/48535/can-grep-return-true-false-or-are-there-alternative-methods
- https://codeinthehole.com/tips/tips-for-using-a-git-pre-commit-hook/
请注意,我没有对此进行测试。
使用 pre-commit
钩子在开发人员端防止它。请注意 git commit --no-verify
将绕过此安全机制。
下面的代码完全阻止了对文件 dir/key1.json
和 key2.json
.
的任何更改
#!/bin/sh
# full paths from the repo root separated by newlines
MUST_NOT_CHANGE='dir/key1.json
key2.json'
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
exec 1>&2
if git diff --cached --name-only $against |
grep --quiet --line-regexp --fixed-strings "$MUST_NOT_CHANGE"
then
echo Commit would modify one or more files that must not change.
exit 1
else
exit 0
fi
下方的 pre-receive
挂钩必须安装在您的中央存储库 上,拒绝任何会修改受保护文件的推送。
#!/bin/sh
# full paths from the repo root separated by newlines
MUST_NOT_CHANGE='dir/key1.json
key2.json'
z40=0000000000000000000000000000000000000000
while read old_value new_value ref_name
do
if [ "$old_value" = $z40 ]; then
# New branch: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
else
against=$old_value
fi
if git diff --name-only $against..$new_value |
grep --quiet --line-regexp --fixed-strings "$MUST_NOT_CHANGE"
then
echo "$ref_name" may commit key, rejected ... >&2
exit 1
fi
done
进行中:
$ git push origin master
Counting objects: 10, done.
Delta compression using up to 40 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (10/10), 820 bytes | 410.00 KiB/s, done.
Total 10 (delta 1), reused 0 (delta 0)
remote: refs/heads/master may commit key, rejected ...
To '<URL>'
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to '<URL>'
我的项目下有几个 .json 文件,其中包含多个键。这些密钥不得受版本控制。我在我的项目中用假的密钥替换了那些实际的密钥,以防止在持续集成时构建失败。
但是,开发人员需要 copy/paste 在他们的笔记本电脑上安装这些文件才能测试应用程序。
现在,问题是开发人员可能会忘记并错误地将它们提交到 git。我想要 运行 一个 pre-commit
脚本来检查修改过的文件,如果添加了其中一个文件,则提交失败。
有什么办法可以做到吗?
您可以在预提交挂钩中执行类似的操作:
FILES_PATTERN='<regexp_to_match_file_names>'
if git diff --cached --name-only | grep -qE $FILES_PATTERN; then
exit 1;
else
exit 0;
fi
这个想法基于这些参考资料:
- https://unix.stackexchange.com/questions/48535/can-grep-return-true-false-or-are-there-alternative-methods
- https://codeinthehole.com/tips/tips-for-using-a-git-pre-commit-hook/
请注意,我没有对此进行测试。
使用 pre-commit
钩子在开发人员端防止它。请注意 git commit --no-verify
将绕过此安全机制。
下面的代码完全阻止了对文件 dir/key1.json
和 key2.json
.
#!/bin/sh
# full paths from the repo root separated by newlines
MUST_NOT_CHANGE='dir/key1.json
key2.json'
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
exec 1>&2
if git diff --cached --name-only $against |
grep --quiet --line-regexp --fixed-strings "$MUST_NOT_CHANGE"
then
echo Commit would modify one or more files that must not change.
exit 1
else
exit 0
fi
下方的 pre-receive
挂钩必须安装在您的中央存储库 上,拒绝任何会修改受保护文件的推送。
#!/bin/sh
# full paths from the repo root separated by newlines
MUST_NOT_CHANGE='dir/key1.json
key2.json'
z40=0000000000000000000000000000000000000000
while read old_value new_value ref_name
do
if [ "$old_value" = $z40 ]; then
# New branch: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
else
against=$old_value
fi
if git diff --name-only $against..$new_value |
grep --quiet --line-regexp --fixed-strings "$MUST_NOT_CHANGE"
then
echo "$ref_name" may commit key, rejected ... >&2
exit 1
fi
done
进行中:
$ git push origin master
Counting objects: 10, done.
Delta compression using up to 40 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (10/10), 820 bytes | 410.00 KiB/s, done.
Total 10 (delta 1), reused 0 (delta 0)
remote: refs/heads/master may commit key, rejected ...
To '<URL>'
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to '<URL>'