2021-08-26

GIT Hooks

GIT the most popular Version-Control tool, has a set of hooks, that is, executable scripts that run whenever a particular GIT event occurs.

Here I am going to describe only client-side hooks which are defined for a particular user and they do not alter other contributors' workflow.

A GIT hook is normally a bash script located in the repository's .git/hooks folder. This folder has a set of default scripts with the extension .sample, once the extension is removed, the script will be executed at the event indicated by its filename. E.g. the pre-commit hook will be the first hook to run just before entering the commit message.

As an example, in my website's repository wktopelican, I have defined the post-commit, pre-commit and prepare-commit-msg. They are stored in a separate folder called githooks, the command:

   git config core.hooksPath ./githooks 

locally set them as the GIT's default hooks. In case I need to clone the repository on a different PC I have only to rerun the previous command.

pre-commit

GIT should block new commits when Pelican encounters errors while processing my text files. First, I redirected Pelican's command line output to a log file (pelican.log). The following pre-commit script will then show eventual errors, and if everything is fine, it will let me write my commit message.

    #!/usr/bin/env bash
    echo -e "Checking for errors:"

    er=$(awk -F ":" -- "$1 - /ERROR/" pelican.log)

    if [ -z "$er" ];then
        echo -e "OK"
        exit 0
    fi

    echo $er
    exit 1

    

prepare-commit-msg

Another thing that I find very useful is to record the total number of articles, drafts, and pages processed by Pelican for each new commit. This gives a good idea if something is missing.

The prepare-commit-msg allows me to create a customized commit message:

    #!/usr/bin/env bash
    awk -F ":" -- '$1 - /Done/' pelican.log >> $1 
    

Note that the message filename is passed by GIT as the first script's argument, here the output of the AWK inline command will be appended to the default commit message.

post-commit

Hooks are not allowed to modify the staging area, but this simple workaround helped me to automate something that I can easily forget, add a new blog post to the repository.

    #!/usr/bin/env bash
    nf=$(git ls-files -o --exclude-standard|grep public)

    if [ -z "$nf" ]; then
        exit 0
    fi
    echo "New untracked content found"
    # stage new files
    git ls-files -z -o --exclude-standard |grep Documents | xargs -0 git add
    git ls-files -z -o --exclude-standard |grep public | xargs -0 git add
    git commit --amend -C HEAD --no-verify
    exit 1
    

Comment

Cygwin/MSYS2/MINGW/Git Bash shell doesn't let you change the file permission with chmod ug+x filename, the file is automatically recognized as executable when it starts with a valid #! header.