This construct:
while ... do ... done &
runs the entire loop as a background process spun off from the current shell and does not wait for it to complete and therefore ignores its exit status. That leaves your script running just one more line:
exit 0
which sets the status for the hook: "all is well, let the commit happen!"
You should not be using a loop in the first place: just use a simple if
test. Do not background it.
(As a general rule for shell tests, beware of lexicographic comparisons. As LeGEC notes in a comment, it should work OK for your particular case. I don't use zsh so I'm not sure if it behaves the same as bash here, but see Why is "[[ 10 < 2 ]]" true when comparing numbers in bash? and How can I compare numbers in Bash? Note further that you only need the numeric hour for the test you're using here, which could simplify things, but if you do want to check both hours and minutes, it may help to split them into two numbers. A handy trick is to use set -- $(date +%H +%M)
so that $1
holds the hour and $2
holds the minute.)