setting up a git post-receive hook

I’m trying to follow along with the instructions http://jekyllrb.com/docs/deployment-methods/ for setting up a git post-receive hook for Jekyll deployment, however, I’m finding them a little dense for me. At that link, there’s a paragraph that says

To have a remote server handle the deploy for you every time you push
changes using Git, you can create a user account which has all the
public keys that are authorized to deploy in its authorized_keys file.
With that in place, setting up the post-receive hook is done as
follows:

  • How to locate the git config file in Mac
  • Pulling the latest code after merging branches
  • MS git provider in Visual Studio: where do I set push target?
  • Can a Rails app be deployed without using Heroku Toolbelt? If so, how?
  • how to use git from another directory?
  • Why GitHub suggest “prefix your version names with the letter v?”
  • Question 1: It’s not clear to me where the ‘user account’ should be created (on Github? on the remote server), and (Question 2) where this authorized_keys file would be. I have a known_hosts file in my home directory on my local machine with keys for github etc. Is that the authorized_keys file?

    The instructions go onto tell you to set up a post-receive hook like this

    laptop$ ssh deployer@myserver.com
    server$ mkdir myrepo.git
    server$ cd myrepo.git
    server$ git --bare init
    server$ cp hooks/post-receive.sample hooks/post-receive
    server$ mkdir /var/www/myrepo
    

    The instruction mkdir myrepo.git is a little unclear to me. For example, I put my Jekyll site into git version control on my local machine, and it gave me this path /Users/me/Sites/nginxjekyll/_site/.git/

    Question 3) Does that mean, then, that, following the mkdir myrepo.git instruction, I should create a directory mkdir /Users/me/Sites/nginxjekyll/_site/.git/ on my remote server? Moving on, it says,

       cp hooks/post-receive.sample hooks/post-receive
    

    However, I don’t have a hooks/post-receive.sample file to copy? In the git repository on my local machine, I have a post-update.sample but not post-receive.sample. Furthermore, when I created the directory mkdir /Users/me/Sites/nginxjekyll/_site/.git/ on my remote server, it didn’t create the post-update.sample file in it.

    Can you clarify these instructions for me if you have a moment. Thank you in advance.

  • Git is doing very slow commits on a Samba share. What can I do to speed it up?
  • Remove file from repository under git
  • How do I disable “git requirement” pop up that appears whenever I open RStudio?
  • Eclipse EGIT: Current branch not configred for pull
  • What git commands do “hexo init <folder>” exactly do?
  • Why TFS with GIT is not working from command line?
  • One Solution collect form web for “setting up a git post-receive hook”

    Question 1: They are referring to the user on the remote server.

    Question 2: This depends, two scenarios: 1. You will need to add the public key of your local user to push to your remote server. 2. You will need to add a public key to a the local user who runs the post-receive hook if an ssh is required to deploy to another server. Most likely only 1 is your concern and 2 is not because the remote server will house the remote git repo and the www server.

    This means you add the public key to the authorized_keys file in a linux/unix environment. This file is typically located in /home/$USER/.ssh/authorized_keys The authorized_keys file is located in the same directory as the known_hosts file for a user.

    Question 3: They are explaining how to setup the remote git repository. It does not need to be at the same path as your local repository.

    OK – now to clarify what is actually going on here. The tutorial is teaching you how to setup a remote repository that will deploy a jekyll install every time it is pushed to.

    This means that if you have a github repo, you cannot setup the server-side hook there. Rather you would set up a new remote on your remote server. So say that you log into your server (with ssh typically), run pwd to learn your full path or set it in an environment variable:

    $DIR=`pwd`
    

    Now you can create a bare repo on this server:

    git init --bare $DIR/<SOMEDIRNAME>.git
    

    Now you have a remote bare git repository on your server. Next you need to add the hook that allows it to deploy your Jekyll site upon receiving a push. The site you have listed has a rather simple deploy, but basically all it is doing is making the _site dir the served html pages, you could do this several ways, I suggest that you do it without disrupting your users as much as possible, here is a sample script that might do such a thing:

    #!/bin/bash
    # Assuming a directory structure for www:
    # $www_root/releases 
    # $www_root/shared
    # $www_root/current
    # all releases go in releases dir as timestamps dirs
    # any logs or other shared items go in shared dir - shared/logs
    # current is a symlink to latest release
    unset GIT_DIR
    WWW_ROOT=/PATH/TO/WWW
    REPO_PATH=/PATH/TO/REPO
    REPO_BRANCH=master
    SITE_DIR=/PATH/TO/_SITE/DIR/IN/REPO
    DATE=$(date +"%Y%m%d%H%M")
    
    # get code
    if [ ! -d $WWW_ROOT/shared/git_maint ]; then 
      mkdir -p $WWW_ROOT/shared/git_maint
      cd $WWW_ROOT/shared/git_maint
      git clone $REPO_PATH $WWW_ROOT/shared/git_maint
      git checkout master
    else
      cd $WWW_ROOT/shared/git_maint
      git pull
      git checkout master
    fi
    
    # do deploy
    if [ ! -d $WWW_ROOT/releases/$DATE ]; then mkdir $WWW_ROOT/releases/$DATE; fi 
    cp -ar $WWW_ROOT/shared/git_maint/$SITE_DIR $WWW_ROOT/releases/$DATE
    ln -s $WWW_ROOT/new_current $WWW_ROOT/releases/$DATE && mv $WWW_ROOT/new_current $WWW_ROOT/current
    
    exit 0
    

    Something like that would be a good deploy. If you save this script on your remote server in the bare repo hooks/post-receive file then it will run each time the repository is pushed to. Just remember to make it executable: chmod 755 hooks/post-receive So if you add this new remote to your git repo with:

    git remote add DEPLOY_PROD user@remote.server.com:/path/to/bare/repo
    

    Then git push DEPLOY_PROD – it will push to your remote and then your remote repo will fire its post-receive hook and then copy the bare repo down to a maintenance directory that can be blown away at almost any point. This directory is then used to cp the site dir to a releases dir and then that is linked up to the main directory.

    Of course all of this is most likely overkill and you can just create a deploy script that runs from you local host to do all this over ssh.

    The problem is you are unable to run server side hooks directly from github for this methodology so you have to work around it. I would suggest you check out capistrano as a deployment strategy – the current/releases/shared dirs and git_maint dir is taken from their schema, it works well.

    Let me know if you would like any help here, I have a lot of experience developing deploy and automated deploy strategies, so depending on your situation, things will vary.

    Git Baby is a git and github fan, let's start git clone.