Tag Archives: git

Logo of the git version control system

Git stop words

If you add development code lines to your file which must not be committed to the code base (e.g. temporarily disabled code, fixated variables, noisy outputs), mark them with the word NOCOMMIT by putting it in a comment, a variable name, …

if(true) {//NOCOMMIT counter > 5 && testThis)
    myNewFeatureToTest();
} else {
    someOtherCode();
}
int NOCOMMIT = 5;
int myVariable = 1;
myVariable = 5; //NOCOMMIT

To activate instant rejection by git as soon as you try to commit this code, do the following:

1. Put this helper script in the file your repository checkout/.git/hooks/showlinenum.awk
2. and the following hook in the file your repository checkout/.git/hooks/pre-commit:

#!/bin/sh
#
# Dismisses the commit if it adds illegal statements (see variable $searchPhrase)

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

# Redirect output to stderr.
exec 1>&2
# ""
# Test for NOCOMMIT and other typical debugging lines
searchPhrase='NOCOMMIT\|(true ||\|(true||\|(false &&\|(false&&'

DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )

. git-sh-setup  # for die
git-diff-index -p -M --cached $against -- | $DIR/showlinenum.awk show_path=1 | grep -E '^.+[0-9]+:\+' |
grep "$searchPhrase" && echo "" && die Rejected commit since the above lines contain illegal statements. Use git commit -n to ignore

# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --

Tip1: best add the stop word to a line which will cause a compile failure if you would commit the lines around it but forgot the one with the stop word (cf. the if condition above).

Tip2: if you want to ignore this hook for one commit, use git commit -n -m "[tag] Your commit message".

Logo of the git version control system

Git hook to prevent WIP commits to certain branches

Git hooks are a great way to automate your workflow and to check for faulty commits. I am using them to prevent work-in-progress commits to the master branch (i.e. commits with a line starting with the string WIP) . But wait – this script differs from the sample found in .git/hooks/pre-commit.sample in two ways:

  1. Only pushes to special heads are inspected. This still allows you to backup your WIP commit on the remote server or to share it with your colleagues but prevents integration into the master branch.
  2. Only commits which would actually be merged into the master are checked – and not all commits ever pushed. This way, even when a WIP commit was pushed to the master in the past, the script does not prevent you from pushing new commits. The pre-commit.sample would explicitly disallow that.

We have two staging areas in our development environment: All pushes to ready/<any name> or directPatch/<any name> trigger our continuous integration process and eventually merge the changes into our master (which you cannot push to directly). Pushes to <developer acronym>/<any name> are always allowed and do not trigger any merging. So we want to check only the pushes to ready and directPatch. Of course, you might want to adapt the script to your needs:

  1. Changing the heads to be checked – see line 24
  2. Changing the word to look for – see line 40

The following hook can be activated by storing it in the file <your repository>/.git/hooks/pre-commit (no file extension)

#!/bin/sh

# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# Information about the commits which are being pushed is
# supplied as lines to the standard input in the form:
#
#   <local ref> <local sha1> <remote ref> <remote sha1>
#
# This sample shows how to prevent push of commits where the
# log message starts with "WIP" (work in progress) and is pushed
# to a refs/heads/ready or refs/heads/directPatch

remote="$1"
url="$2"

z40=0000000000000000000000000000000000000000

IFS=' '
while read local_ref local_sha remote_ref remote_sha
do
	if [[ $remote_ref != refs/heads/ready/* ]] && [[ $remote_ref != refs/heads/directPatch/* ]]
	then
		# Do not check the WIP
		continue
	fi

	if [ "$local_sha" = $z40 ]
	then
		# Handle delete
		:
	else
		# Only inspect commits not yet merged into origin/master
		range="origin/master..$local_sha"

		# Check for WIP commit
		commit=`git rev-list -n 1 --grep '^WIP' "$range"`
		if [ -n "$commit" ]
		then
			echo "Found WIP commit in $local_ref: $commit, not pushing."
			exit 1
		fi
	fi
done

exit 0