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

这个想法基于这些参考资料:

请注意,我没有对此进行测试。

使用 pre-commit 钩子在开发人员端防止它。请注意 git commit --no-verify 将绕过此安全机制。

下面的代码完全阻止了对文件 dir/key1.jsonkey2.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>'