Open In App

Git – Hooks

Last Updated : 07 Apr, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Git is a free and open-source version control system. It is used in software development. Git allows software developers to see the changes they made on the code, it gives them the ability to undo things if necessary and helps a team of people to work together on a project. Here we will be discussing git hooks.

Git hooks provide a way to fire off custom scripts on different events such as during commit, push or rebase, etc. There are two types of hooks present in Git.

  1. Client-Side hooks
  2. Server-Side hooks

Types of Hooks

Client-Side hooks Server-Side hooks
pre-commit pre-receive
prepare-commit-msg update
commit-msg post-receive
post-commit  
post-checkout  
pre-rebase  

Note: There are many other hooks are present except this but we are covering these major ones. Below is the representation for the same:

In order to use git hooks, we must follow some steps first to enable them which are as follows:

Step 1: First we need to change our directory to the below directory as follows:

repository/.git/hooks 

Below is a terminal window screenshot depicting the same as follows:

At first, here we are in the ~/Desktop/GFG directory, which is a git repository. So we have used the below directory command to go to the specific directory. This directory contains all the hooks of a repository.

cd .git/hooks

Step 2: To use a hook first we need to enable it and to enable a hook we have to remove the .sample extension from the end of the files. In order to do so, we can use the following command as follows:

mv hookname.sample hookname 

Below is a terminal window screenshot depicting the same as follows: 

Here we have removed the .sample extension of the pre-commit hook and enabled it.

Step 3: After that, we have to provide the execute permission for the hook. To do so we can use the following command as follows:

chmod +x hookname

Now we can write our scripts in different languages like Python, Bash, or Shell. In order to write a script first, you need to specify that in the first line of the script.

The first line of the script will be:

A. Python

#!/usr/bin/env python

B. Shell

#!/bin/sh

C. Bash

#!/bin/bash 

Note: We will be using Python scripts for this article.

Different Types of Hooks

A. Client-Side Hooks

1. pre-commit: The pre-commit hook runs on the git commit event. This can be used for Static analysis, Linting, Spell-checks, and Code style checks. It takes zero arguments and exiting with a non-zero status aborts the commit operation.

Let’s consider the simple script below for a demonstration. This script when runs will print the “This is a git hook” message on the console in case the commit is aborted. As here we have provided an exit code 1 which is a non-zero exit status that told git to abort the commit operation.

Example:

Python3




#!/bin/python
import sys
 
 
def main():
    print("This is a git hook")
    sys.exit(1)
 
 
if __name__ == "__main__":
    main()


Here is the output when any commit operation is done on the repository –

2. prepare-commit-msg: The prepare-commit-msg hook is run before the commit message editor is fired up but after the default message is created. It is useful for editing the default message before the commit author sees it. It is also useful for adding Ticket-ID, Branch name, Style Checklist, and Rules for commits. It takes three parameters they are as follows:

  • The path to holds the commit message so far
  • The type of commit
  • commit SHA-1 information 

3. commit-msg: This is useful to validate a commit. Developers can provide rules to validate the commit state or the commit message using this hook. Like it is helpful for spell-checks of commit messages. This hook takes one parameter and it is the path to a temporary file that contains the commit message. Let us take one small code snippet for this which is below as follows:

Example:

Python3




#!/bin/python
import sys
def main():
        with open(sys.argv[1],'a+') as fp:
            # fp.read() can be used to read the commit msg
            fp.writelines(" and issue id is #1") #appending with issue id
            sys.exit(0) # indicates success
 
if __name__=="__main__":
    main()


Here during the commit operation, the commit message is appended with the issue id.

4. post-commit: This hook runs after the commit operation successfully completed. This hook can be useful to provide notifications and it doesn’t take any parameters. Here is a small code snippet that gives an acknowledgment after committing.

Example:

Python3




#!/bin/python
import sys
def main():
    print("Satyajit Ghosh successfully committed the changes in the repo")
    sys.exit(0) # indicates success
 
if __name__=="__main__":
    main()


5. post-checkout: The post-checkout hook runs after the git checkout operation. It can be used to set up a working directory, auto-generating documentation, etc. It works similar to the post-commit hook. This hook accepts three parameters as follows:

  • The ref of the previous HEAD
  • The ref of the new HEAD
  • A flag indicating branch checkout(1) or a file checkout (0).

6. pre-rebase: The pre-rebase hook runs before the rebase operation. A script can be used to validate the rebase matches the workflow or not. If not then a non-zero exit code from the script will halt the rebase process.

B. Server-Side Hooks

1. pre-receive: This hook reacts to git push and updates the references in its repository. It takes no arguments but for each ref to be updated it receives standard input in this format.

<old-value> SP <new-value> SP <ref-name> LF>

where <old-value> is the old object name stored in the ref, <new-value> is the new object name to be stored in the ref, and <ref-name> is the full name of the ref. If the hook exits with a non-zero status, none of the refs will be updated.

2. update: Before updating the ref on the remote repository, the update hook is invoked. Its exit status determines the success or failure of the ref update. It takes three arguments as follows: 

  • the name of the ref being updated
  • the old object name is stored in the ref
  • and the new object name to be stored in the ref.

3. post-receive: It executes on the remote repository once all the refs have been updated. It takes no arguments but gets the same information as the pre-receive hook does on its standard input.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads