Skip to content

Instantly share code, notes, and snippets.

@Dreded
Last active December 21, 2022 22:45
Show Gist options
  • Save Dreded/ea8c4db738d55e1bc6836df0e75f1d56 to your computer and use it in GitHub Desktop.
Save Dreded/ea8c4db738d55e1bc6836df0e75f1d56 to your computer and use it in GitHub Desktop.
Use Git Hooks to Publish via SSH to any SSH Client

Easily use git hooks to publish to a SSH server.

Instea of uploading to a middle man like github then doing a pull on your production or staging server you can use this trick to push directly to the production or staging server over SSH

These instructions will show how to use a git hook( in this case post-receive ) to do whatever is needed on the server(receiving) side.

This allows for high security(no middle men) and high flexibility as you can use Bash scripts to do whatever is required.

Prerequisit

  1. Know how to use GIT, Terminal etc.
  2. Have a local working-working copy ready
  3. Have SSH access to your server using private/public key

Procedure Outline

  1. Create a folder to deploy to on production server (i.e. your httpds folder)
  2. Use git to add a bare repository on the productions(remote) server
  3. Add the post-receive hook script to the bare repository (and make it executable)
  4. Add the remote-repository resided on the production server to your local repository
  5. Push to the production server, relax.

Procedure Detail

1. Have a local working-working copy ready(git init done)

This can be any branch, not only master.

2. Create a folder to deploy to (or skip this to use an existing one like /var/www)

ssh into your remote server: ssh -p 2222 user@server.com mkdir ~/deployment-folder

3. Add a bare repository on the remote server

Create a bare repository, this will essentially be the .git folder contents of a normal repo.(doesnt need to end in .git) git init --bare ~/production.git

4. Add the post-receive hook script

vim ~/production.git/hooks/post-receive

#!/bin/bash
TARGET="/home/webuser/deployment-folder"
GIT_DIR="/home/webuser/production.git"
BRANCH="master"

while read oldrev newrev ref
do
	# only checking out the master (or whatever branch you would like to deploy)
	if [ "$ref" = "refs/heads/$BRANCH" ];
	then
		echo "Ref $ref received. Deploying ${BRANCH} branch to ${TARGET}..."
		git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH
	else
		echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
	fi
done

chmod +x post-receive

5. Add remote-repository localy

Now we add the this bare repository to your local system as a remote. Where "production" is the name you want to give the remote. This also be called "staging" or "live" or "test" etc if you want to deploy to a different system or multiple systems.

cd ~/path/to/working-copy/ git remote add production user@yourserver.com:production.git if you need to use an alternative port you can do...
git remote add production ssh://user@yourserver.com:2222/home/webuser/production.git

Make sure "production.git" coresponds to the name you gave in step 3.

6. Push to the production server

Now you can push the master branch to the production server:

git push production master

An Example of post-receive that would handle a DEV and PRODUCTION branch

#!/bin/bash
TARGET_PRODUCTION="/home/myUser/www/myWebsite-production"
TARGET_DEVELOPMENT="/home/myUser/www/myWebsite-development"
GIT_DIR="/home/myUser/www/myWebsite.git"
BRANCH_PRODUCTION="master"
BRANCH_DEVELOPMENT="development"

while read oldrev newrev ref
do
        # only checking out the master (or whatever branch you would like to deploy)
        if [ "$ref" = "refs/heads/$BRANCH_PRODUCTION" ];
        then
                echo "Ref $ref received. Deploying ${BRANCH} branch to production..."
                git --work-tree=$TARGET_PRODUCTION --git-dir=$GIT_DIR checkout -f $BRANCH_PRODUCTION
        elif [ "$ref" = "refs/heads/$BRANCH_DEVELOPMENT" ];
        then
                echo "Ref $ref received. Deploying ${BRANCH} branch to development..."
                git --work-tree=$TARGET_DEVELOPMENT --git-dir=$GIT_DIR checkout -f $BRANCH_DEVELOPMENT

        else
                echo "refs/heads/$BRANCH_DEVELOPMENT"
                echo "Ref $ref received. Doing nothing: $ref not recognized."
        fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment