Setup Notes

Git Deployment

After trying, failing and despairing that I'd ever figure out how to use git to deploy files to a production or demo web hosting service, I finally cobbled it together, and wanted to save and record it here.

The pieces are as follows:

  1. Have a local git repository created.
    This one should live on your laptop or iPad or whatever you do your actual content creation or development or coding or whatever project deliverables you make.
  2. Create a deploy folder and target folder on the web server.
    You need to have shell (preferrably SSH) access to the web server. The server itself must be able to run git, and it should be UNIX/Linux based for these instructions to work. For what it's worth, I have shared hosting on Dreamhost, and that's enough.
  3. Add a bare repository to the deployment folder that you just created.
    This will create a really cluttered looking folder once the "bare" repository is created. I had no idea that I should expect this the first time I tried it, so be prepared. The subfolder you'll want to keep in mind is "./hooks" in the "bare" repository.
  4. Add the "post-receive" hook for the appropriate git push event
    This is where you'll need the fixed up script that helpful commenter used. Still, you have to use your noggin, to keep the different directories straight while you set this up. Also, don't forget to make it executable (or it won't run when it's supposed to).
  5. Add the remote repository to your local git repository.
    This remote is how you'll kick off deployments.
  6. Every time you are ready to deploy, push your whole repository to a deployment.

Details

  1. Local git repository
    If you aren't familiar with git basics, you ought to find a good primer or introductory guide. Pick one with a style you like. There are plenty of choices.
  2. Deploy and Target Folder
    For this method to work, you need a local git repository, on the computer(s) you use to create your code, content, or whatever you're keeping and deploying with git. You also need a deploy directory, which really just exists to receive the git push you do for your deployment, AND you need the actual "production" directory, which I refer to here as the Target directory. So the deploy folder is the middleman directory. Create it and the Target or production directory, then configure the deploy folder with the next two steps.
    For my part, on my host:
    ssh user@hostname
    cd malcolmgin.com
    mkdir gitDeploy (This is the deploy directory)
    mkdir TheCodeTrain (This is the target/production directory)
  3. Bare repository
    As I noted above, this puts a whole lotta files in the directory you use for the deploy (middleman directory). Enough that it seriously put me off the first time I tried to get this done.
    Commands on my host:
    cd gitDeploy
    git init --bare . (Note the "." at the end.)
  4. The Hook
    The hook, "post-receive", is an executable script file you create in the "hooks" subdirectory of your deployment repository. You have to create it, paste in the template provided, and edit the template appropriately, save, and then use the chmod command to be sure that the file can be executed (by the deployment repository).
    The template script:
    #!/bin/bash
    set -eu

    TARGET="[production file path]"
    GIT_DIR="[deployment file path]"
    BRANCH="[the branch name you want for deployments]"

    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 production..."
    git --work-tree="$TARGET" --git-dir="$GIT_DIR" checkout -f
    else
    echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
    fi
    done

    On my host, filled out:
    #!/bin/bash
    set -eu

    TARGET="/home/perigee/malcolmgin.com/TheCodeTrain"
    GIT_DIR="/home/perigee/malcolmgin.com/gitDeploy"
    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 production..."
    git --work-tree="$TARGET" --git-dir="$GIT_DIR" checkout -f
    else
    echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
    fi
    done

    So I take this template and I create a file named "post-receive" in the hooks subdirectory of the deployment directory on my web host. Then I make it executable:
    cd hooks
    vi post-receive

    (Then in vi I put the editor into insert mode, I paste in the filled out template above, and I save the file and quit vi. Then I use chmod to make the file executable:)
    chmod post-receive 755
    Your business now done on your web most, you should now be able to exit your SSH session and work on your local repository.
  5. Remote Repository
    It remains, now, to add your remote repository (and your SSH key, if needed), to your local setup. For the remote repository, my URL for the deployment repository is "ssh://username@malcolmgin.com/home/perigee/malcolmgin.com/gitDeploy" so the command in my local repository is:
    git remote add production ssh://username@malcolmgin.com/home/perigee/malcolmgin.com/gitDeploy
    You can test whether this worked by using the command, git remote show production. If you have an error related to a missing key, ensure your key is properly configured in your ~/.ssh directory.
  6. Push/publish/deploy
    You'll obviously want to run this through its paces and troubleshoot any problems you might have, but assuming it's all working correctly, you should be able to deploy to production by using git or a git-supporting app or application to push to "production" which is now defined properly as a remote repository. Once you do that, the post-receive script will copy valid updated files that are part of the "master" (or whatever you decide to call it) branch of your repository to the target, or production, directory.
    If you need to run the git command at the command line, for this setup it would be:
    git push production master

References

Of assistance were the following: