Using Git To Deploy Code

https://mikeeverhart.net/2013/01/using-git-to-deploy-code/

Setting Up The Remote Server

The following instructions apply to your remote (eg: Production/Staging) server(s).

1. Create a new directory for your git repository (preferably outside of your www directory – in our case /var/www/site.com/):

$ sudo mkdir -p /var/www/site.com/git/project_name.git
$ cd /var/www/site.com/git/project_name.git

my example:

$ sudo mkdir -p /var/www/site.com/staging.git
$ cd /var/www/site.com/staging.git

2. Create a bare (empty) git repository inside of your new directory:

$ sudo git init --bare

3. Create a post-receive “hook”. This hook gets executed automatically each time you push code changes to the server. In our case, we’ll use the hook to checkout the latest code from our repository.

$ sudo nano /var/www/site.com/git/project_name.git/hooks/post-receive

my example:

$ sudo nano /var/www/site.com/staging.git/hooks/post-receive 

and add the following:

#!/bin/sh 
GIT_WORK_TREE=/var/www/site.com/html git checkout -f

Update GIT_WORK_TREE, replacing /var/www/site.com/html with the root directory of your project (where you would normally upload the files).

Note: You can add other commands and shell code to the post-receive hook to do things like chmod files and directories, call other scripts, etc. each time you push updated code to the server.

4. Make your post-receive hook executable:

$ sudo chmod +x hooks/post-receive

Setting Up The Local Server

The following instructions apply to your local (eg: Development) server.

5. Navigate to wherever your git repository is located:

$ cd /var/www/html/project_name

my example using vagrant:

$ cd projects/dev/project
$ vagrant up
$ cd /html/site.com  # or cd /sites/site.com

6. Add a remote source that references the server and repository we setup in the previous steps:

$ git remote add production ssh://site.com/var/www/site.com/git/production.git

my example:

$ git remote add production ssh://username@staging.site.com/var/www/site.com/staging.git

You can use whatever you want in place of staging (such as production or server1). Replace site.com with your server address, and be sure that /var/www/site.com/git/project_name.git matches the directory you created in step 1.

7. Do an initial push to the remote server, which will setup the master branch. If your branch is named something other than master then use its name in place of master in the following command:

$ git push staging +master:refs/heads/master

Deploying Code

Each time that you make changes to your code, commit them as usual (using $ git commit … , etc.), and then run the following command to deploy your changes to the remote server:

$ git push staging master

If your branch isn’t named master then use your branch name instead. The main point here is the format of the command:

$ git push <remote server> <branch name>

And that’s it! Now you can easily deply code across multiple servers using only a few commands. See ERRORS & SOLUTIONS below if there is an error when you try to push to the server.

Multiple Servers and/or Branches

If you have multiple servers and/or branches (such as development, staging, and production) then you’ll need to repeat all of the steps for each one. Here’s the same steps from above, only using staging for the server and the branch in place of production (server) and master (branch):

Remote Server

$ mkdir -p /home/git/project_name.staging.git
$ cd /home/git/project_name.staging.git

$ git init --bare

$ cat > hooks/post-receive 
#!/bin/sh 
GIT_WORK_TREE=/var/www/project_name git checkout -f
    
$ chmod +x hooks/post-receive

my example:

$ mkdir -p /var/www/site.com/git/staging.git
$ cd /var/www/site.com/git/staging.git

$ git init --bare

$ cat > hooks/post-receive 
#!/bin/sh 
GIT_WORK_TREE=/var/www/site.com/html git checkout -f
    
$ chmod +x hooks/post-receive

Local Server

$ cd /var/www/project_name
$ git remote add staging ssh://staging.website.com/home/git/project_name.staging.git

$ git push staging +staging:refs/heads/staging

my example:

$ cd /var/www/html/project_name
$ git remote add staging ssh://username@site.com/var/www/site.com/git/staging.git

$ git push staging +staging:refs/heads/staging

Updating

$ git push staging staging

Permissions

It’s important that file permissions are set so that the Apache (or whatever server you’re using) user can write to the directory that you defined as GIT_WORK_TREE. If not, then the files can’t be pulled from the repository and placed in the correct directory. This is especially true if you created your repository outside of your root www directory (as recommended).

Changing Remote Server Settings

If you ever need to change the information for one of your remote servers, the easiest way is to edit the git config file. On your local server, open the config file located inside of your git repository (.git/config). By default, the config file is pretty bare, so you won’t have any trouble finding what to edit:

...
[remote "production"]
        url = ssh://username@website.com/home/git/project_name.git
        fetch = +refs/heads/*:refs/remotes/production/*
...

ERRORS & SOLUTIONS

Permissions

https://stackoverflow.com/questions/13146992/fatal-unable-to-create-temporary-file-home-username-git-myrepo-git-objects

If you see an error with something like:

fatal: sha1 file '<stdout>' write error: Broken pipe
error: remote unpack failed: unable to create temporary object directory
error: failed to push some refs to 'ssh://user@site.com/var/www/site.com/staging.git'

Do this, changing user to your username:

$ sudo chown user /var/www/staging.site.com/staging.git

or just change the remote server setting file in the local git config to use ‘root’ as the user instead of a username. You will be prompted for the login password.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.