How can I prevent a file (.json) to be commited with a git hook ?
I have a .json which is on the server yet. So I can not use an gitignore. But now
A pre-commit
sample:
#!/bin/bash
ipath="foo/bar.json"
git diff --cached --name-only | if grep -qE "^$ipath$";then
git reset HEAD -- "$ipath"
echo "Warning: $ipath is removed from the index. It's not allowed to be committed."
fi
git diff --cached --name-only
lists all the changed files that are going to be committed. If foo/bar.json
is found in the list, then git reset HEAD -- foo/bar.json
removes it from the index so that it's not committed but left in the working tree.
It works fine for you. However you can't ensure it does for others. For example, other contributors may delete it from their local repositories. What you need is a pre-receive
hook in the central repository, the one on the server side. It rejects any push if the incoming commits touch foo/bar.json
.
A pre-receive
sample:
#!/bin/bash
ipath="foo/bar.json"
zero="0000000000000000000000000000000000000000"
while read old new name;do
if [ "$zero" == "$old" ];then
#creating new ref, do something here
continue
fi
if [ "$zero" == "$new" ];then
#deleting a ref, do something here
continue
fi
#updating a ref, check if the incoming commits touch `foo/bar.json`
git diff $old..$new --name-only | if grep -qE "^$ipath$";then
c=$(git log $old..$new --pretty=%H -- $ipath)
echo "Error: $ipath is changed in:"
echo $c
echo "Error: $ipath is not allowed to be committed and pushed."
exit 1
fi
done
The contributors receive the error message after git push
. They must amend their commits and remove the changes of foo/bar.json
before another try. In pre-receive
, you need to deal with deleting a ref
and creating a ref
if necessary.