DEV Community

dejanualex
dejanualex

Posted on

Short intro to Git Hooks

Git-hooks = scripts with a "special" name, located in the .git/hooks directory inside the repository which are triggered every time a particular event occurs in the Git repository.

They allow you to customize Git's internal behavior and perform customizable actions at certain points in GIT's execution.

There are different types of commit hooks but we will cover some of the client-side workflow hooks:

  • pre-commit (linting, spell-checks, code style stuff)
  • prepare-commit-msg (alter the default commit message or create a complete a new one)
  • commit-msg (invoked git-commit and git-merge and allow to perform a check of the commit message)
  • post-commit (invoked git-commit, it takes no parameters, and is invoked after a commit is made)
  • pre-rebase
  • pre-push
  • post-rewrite
  • post-merge (invoked by git-merge, which happens when a git pull is done on a local repository)
  • post-checkout (invoked when a git-checkout is run after having updated the worktree)

A complete list of git-hooks can be found here

We will demonstrate the power of git-hooks by "enforcing" a certain standard with respect to the commit messages. (e.g. the commit message should contain the task identifier e.g. TASK-5463)

This is a two step process.

1) Create our script, e.g. in the root of our repo we can create commit-msg.py file.

#!/usr/bin/python

import sys
import re

def line_valid(line_no, line):
    """
    return True if line is ok according with the verification
    """
    if line_no == 0:
        # first line should have the task identifier e.g TASK-4351
        return re.match("^TASK-\d{1,5}.*", line)

def show_rules():
    """
    Rules for a great git commit message style
    """
    print("Please follow the rules add task/feature TASK-xxxx in the name of the commit msg""")

def main():
    print("Args are {}".format(sys.argv))
    # read commit-msg
    with open(sys.argv[1], "r") as fp:
        lines = fp.readlines()
        for line_no, line in enumerate(lines):
            #print(line_no,line)
            if not line_valid(line_no, line):
                show_rules()
                sys.exit(1)
    sys.exit(0)

if __name__=="__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

2) Create a symbolic link.

cd <REPO>/.git/hooks
ln -s <REPO>/commit-msg.py ./commit-msg
Enter fullscreen mode Exit fullscreen mode

Using this simple hook, we managed to enforced (based on our regex) that a commit message should start with the task id

Git msg

Important aspects:

  • Git hooks are not checked into source control by default
  • The user can bypass locally pre-commit and commit-msg hooks by passing --no-verify flag

Top comments (0)