Git Post-Receive Hook: A Practical Guide (with Examples)

Updated: January 28, 2024 By: Guest Contributor Post a comment

Introduction

Git hooks are powerful tools that can be used to automate tasks and enhance your workflow. Specifically, a post-receive hook in Git is a script that runs on the server-side after a successful push action. This guide will walk you through the basics, provide several practical examples, and demonstrate advanced use-cases of Git’s post-receive hooks.

What is a Git Post-Receive Hook?

A post-receive hook is a script that gets executed every time the ‘receive’ phase of a Git push transaction is completed. This is the point at which updates to the repository are accepted and could potentially be deployed to production, trigger notifications, or kick off builds and tests.

Setting up a Basic Post-Receive Hook

Here’s how to set up a basic post-receive hook:

  1. Navigate to your repository on the server.
  2. Go to the .git/hooks directory.
  3. Create a file named post-receive.
  4. Make the script executable with chmod +x post-receive.
  5. Edit the post-receive script to perform the desired tasks.

Example: The following is a simple script that will just echo a statement to confirm the receipt of a push:

#!/bin/bash
echo "Post-receive hook activated!"

Example Use Case: Deploying Code

Deployment automation is a common use case for post-receive hooks. Below is a step-by-step example of deploying a website after a push:

  1. Let’s assume you have your website files in a public directory within your Git repository.
  2. In the post-receive script, you would generally write commands to copy files to your web server’s document root after the push.

Sample post-receive hook for deployment:

#!/bin/bash
git --work-tree=/var/www/html --git-dir=/home/user/repo.git checkout -f
echo "Website deployed successfully!"

This code checks out the latest code into the document root of the web server, thereby updating the website instantly after the push.

Advanced Usage

Triggering Continuous Integration (CI) Builds

Using a post-receive hook, you can trigger a CI build process. This example assumes you have a CI system like Jenkins:

#!/bin/bash
curl -X POST -d 'payload={"ref": "refs/heads/main"}' http://ci-server.job/trigger-build

This hook uses curl to send a POST request to your Jenkins server to trigger a new build for the main branch.

Managing Multi-Environment Deployments

The script can identify branches and deploy appropriate environments:

#!/bin/bash
while read oldrev newrev refname
do
  if [[ $refname = 'refs/heads/main' ]]; then
    # Commands to deploy to production
    echo "Production deployed!"
  elif [[ $refname = 'refs/heads/staging' ]]; then
    # Commands to deploy to the staging environment
    echo "Staging deployed!"
  fi
done

Executing Database Migrations

Database updates are sensitive operations that can also be automated cautiously:

#!/bin/bash
# Assume we're on the main branch and ready for production deployment
/database/migrate --to-latest

This executes a database migration script to bring your production database up to date with your latest code push.

Enhanced Notifications:

A sophisticated post-receive hook can parse commit messages and send notifications:

#!/bin/bash
while read -r oldrev newrev refname
do
  echo "Commit pushed by $(git log -1 --pretty=format:'%an' $newrev)." | mail -s "Git Commit Notification" [email protected]
done

This sends an email summarizing the push event to a team email address.

Security and Error Handling

While the possibilities are extensive with post-receive hooks, you must incorporate proper error handling and security measures to protect your deployments from errors and malicious code.

Error Logging

Ensure to log any errors from your post-receive script activities for debugging:

#!/bin/bash
...some script...
if ! deploy_to_production; then
  echo "Deployment failed!" >&2
  # Logging into a file
  echo "$(date): Deployment failed" >> /var/log/deploy_errors.log
fi

Parameter Verification

Validating refnames, commits, and other parameters prevent mishandling of your hook script.

#!/bin/bash
...some script...
if [[ "$refname" != 'refs/heads/main' ]]; then
  echo "Invalid reference. Only the main branch can be deployed." >&2
fi

Conclusion

Git post-receive hooks offer immense potential for automating your deployment and integration workflows. Remember that while automation is powerful, it should always be implemented with safeguards and thorough testing. You’ll find that with a bit of scripting and creativity, post-receive hooks can significantly simplify and enhance your operations.