For web project or other server side project, we need auto-deploy. For this, we need run some scripts after we push the git commits. That’s why post-update here.

   If we put script file under git-dir/hooks/ and name it with post-update, and chmod -x for it. The file will run after we push some commits to the git repository. You can yous any scripting language you like, such as bush, python, ruby, julia, PHP, Node.js… Compiled as well of cause, but not as easy to read and edit as scripting languages.

#Example 0.

   For simple scripts, bash is convenient.

#!/bin/bash
git --work-tree=/path-to/project-dir/ checkout "`git rev-list --tags --max-count=1`" -f >/dev/null

This script will checkout the newest tag to the work directory. It’s frequently-used.

#Example 1.

   This is an example of Laravel project, so we using PHP.

#!/usr/bin/env php
<?php

$product_dir= '/path-to/project-dir/';
$test_dir= '/path-to/test-dir/';

switch( $argv[1] )
{
	case 'refs/heads/migrate':
		`git --work-tree=$test_dir checkout -f migrate`;
		`$test_dir/artisan migrate:fresh --seed`;
	
	case 'refs/heads/test':
		`git --work-tree=$test_dir checkout -f test`;
		`composer --working-dir=$product_dir dump-autoload`;
		`$product_dir/artisan migrate`;
	break;
	
	case 'refs/heads/composer':
		`git --work-tree=$test_dir checkout -f composer`;
		`composer --working-dir=$test_dir update`;
		`$test_dir/artisan vendor:publish --all`;
		`git --work-tree=$test_dir checkout -f test`;
		`composer --working-dir=$product_dir dump-autoload`;
		`$product_dir/artisan migrate`;
		
		`git --work-tree=$product_dir checkout -f composer`;
		`composer --working-dir=$product_dir update`;
		`$product_dir/artisan vendor:publish --all`;
	
	case 'refs/heads/product':
		`git --work-tree=$product_dir checkout -f "\`git rev-list --tags --max-count=1\`"`;
		`composer --working-dir=$product_dir dump-autoload`;
		`$product_dir/artisan migrate`;
		`$product_dir/artisan view:clear`;
		`$product_dir/artisan route:cache`;
	break;
}

   This time, we do different things according to different bushed branch. When test branch is pushed, we checkout it to the test directory, and apply the migrations of DB. When migrate branch is pushed, we refresh the DB of the test environment, When project branch is pushed, we checkout the newest tag to the project environment, then apply migrations and clear view cache and rebuild route cache.

#Example 2.

   Here is the deploy script of this blog, on ruby.

#!/usr/bin/env ruby

# import rugged (the git API for ruby base on libgit2), we need install it by gem first 
require 'rugged'

# import jekyll, install by gem too 
require 'jekyll'

git_repository= '/path-to/git-repository/'
project_dir= '/path-to/project-dir/'
web_root_dir= '/path-to/web_root_dir/'

repo= Rugged::Repository.new( git_repository, )

# get the list of git tag.
tags= repo.tags.map{ |tag| tag.target }

# build the walker from master 
walker= Rugged::Walker.new( repo, )
walker.push( repo.head.target, )

# walk back and find the newest tag in the master branch 
latest_tag= walker.find{ |commit| tags.include?(commit) }

# checkout this tag 
repo.workdir= project_dir
repo.checkout( latest_tag.oid, :strategy=>:force, )

# build the jekyll project 
config= Jekyll.configuration( { 'source'=>project_dir, 'distination'=>web_root_dir, }, )
site= Jekyll::Site.new( config, )
site.process

   Here we use API instead of CLI to access git. Maybe a little inconvenience than CLI, but the API is more powerful. The libgit2 is a great lib of git API, it support more than a dozen of languages and environments.

   Above examples are the deploy scripts of real using in my work. Share the code, and more to the point, share the line of thought. We hope to bring help.