Search Knowledge

© 2026 LIBREUNI PROJECT

Git Hooks

Automating Development

Git has a way to fire off custom scripts when certain important actions occur. These are called Hooks. They are essentially the “events” of the Git lifecycle.

There are two groups of hooks:

  1. Client-side: Triggered by operations like committing and merging.
  2. Server-side: Triggered by network operations like receiving pushed commits.

Client-Side Hooks

Hooks are stored in the .git/hooks directory of your repository. By default, Git populates this folder with sample scripts (pre-commit.sample, etc.). To enable a hook, you simply create an executable file with the name of the hook (no extension).

pre-commit

This hook runs before you even type a commit message. It is used to inspect the snapshot that is about to be committed.

  • Use cases: Linting code, checking for trailing whitespace, running unit tests.
  • Exit Code: If the script exits non-zero, the commit is aborted.

Example pre-commit script (Bash):

#!/bin/sh
echo "Running tests..."
npm test
if [ $? -ne 0 ]; then
    echo "Tests failed! Commit aborted."
    exit 1
fi

prepare-commit-msg

Run before the commit message editor is fired up but after the default message is created.

  • Use cases: Automatically prepending the ticket number from the branch name to the commit message.

commit-msg

Takes one parameter (the path to the temporary file containing the commit message).

  • Use cases: Enforcing a commit message pattern (e.g., “feat: …”).

post-merge

Runs after a successful merge command.

  • Use cases: Re-installing dependencies (like npm install) if package.json changed.

Server-Side Hooks

These scripts run on the server (remote) when it receives a push.

pre-receive

The first script to run when handling a push from a client. It takes a list of references that are being pushed from stdin.

  • Use cases: Rejecting force pushes to main, enforcing access control.

update

Similar to pre-receive, but runs once for each branch the pusher is trying to update.

post-receive

Runs after the entire process is completed.

  • Use cases: Triggering a CI/CD build, notifying Slack/Email, deploying to production.

Sharing Hooks

Hooks are stored in .git/hooks, which is not version controlled. This means if you clone a repo, you don’t get the hooks.

To share hooks with your team, you have two common strategies:

  1. Symlinks: Store scripts in a scripts/hooks folder (which is versioned) and symlink them to .git/hooks.

    git config core.hooksPath scripts/hooks
    
  2. Husky (Node.js): A popular tool for JavaScript projects that automatically configures hooks.

    // package.json
    "husky": {
      "hooks": {
        "pre-commit": "npm test"
      }
    }
    

Bypassing Hooks

Sometimes you need to commit code that you know fails the linter (e.g., a WIP save). You can bypass client-side hooks with:

git commit --no-verify

(or -n)

git
1# We will simulate a pre-commit hook mechanism
2git init
3mkdir .git/hooks
4 
5# Create a pre-commit hook that fails
6echo "#!/bin/sh" > .git/hooks/pre-commit
7echo "echo 'Hook says NO!'" >> .git/hooks/pre-commit
8echo "exit 1" >> .git/hooks/pre-commit
9chmod +x .git/hooks/pre-commit
10 
11# Try to commit
12echo "change" > file.txt
13git add file.txt
14git commit -m "Try me" || echo "Commit failed as expected"

Where are Git hooks stored by default?

Bypassing Hooks

# You need to commit immediately and skip the pre-commit hook.
git commit  -m "Emergency fix"
Previous Module Tags and Releases