Commit Preventer

HomeAbout
Wed 21 Aug 2024

Have you ever accidentally committed a change to Git? I used to do it all the time. For example, I would add some temporary logging code to help with debugging, then find and fix the bug, and in my excitement, forget to remove the logging code before committing the fix. That mistake is easy to remedy, but it's a nuisance, so I decided to put a stop to it.

The script below, when installed as a Git pre-commit hook, looks for the string "<><>" in the lines being committed. If it finds that string, it cancels the commit. So whenever I add some code that I know I won't want to commit, or that really has to be fixed before committing, I add "<><>" in a comment, and can be confident that it won't make it into my repo. Note that the script only prevents the commit if the pattern appears in a line that's actually being committed. If I haven't staged the marked lines, even if other unmarked lines in the same file have been staged, the commit will go through.

If the hook prevents a commit, it displays a message like this:

Commit rejected because "<><>" found in staged hunk in "src/…/commit-preventer.html".

To install the hook, just add a symbolic link to it from .git/hooks/pre-commit:

ln -s pre-commit.sh .git/hooks/pre-commit

Some things just aren't fit to commit.

#!/bin/sh

FILES_PATTERN='\.(css|html|js|lisp|org|scm|sld|svg|tex|txt)$'
FORBIDDEN='<><>'
exit=0
files=$(git diff --name-only --staged \
  | grep --extended-regexp $FILES_PATTERN)
for f in $files; do
  if git diff --staged "$f" \
    | grep \
      --fixed-strings \
      --quiet \
      "$FORBIDDEN"; then
    echo "Commit rejected because \"$FORBIDDEN\" found in staged hunk in \"$f\"."
    exit=1
  fi
done
exit $exit