Using Git to Deploy Code

Git Logo

Like many other programmers, I use git on a daily basis to manage my code. In fact, I believe git is so useful that I list it as a required skill whenever I post job openings for programmers at work. Although it’s used by a lot of people, I often find that git is not utilized to its full potential. Mainly, I find that programmers will use git to version their code, but they still upload files through FTP or some other method. This article is going to show you how I use git to quickly and easily deploy code across multiple servers without using FTP.

Setting Up Your Remote Server

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

  1. Create a new directory for your git repository (preferably outside of your www directory):
    $ mkdir -p /home/git/project_name.git
    $ cd /home/git/project_name.git
    
  2. Create a bare (empty) git repository inside of your new directory:
    $ 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:
    $ cat > hooks/post-receive 
    #!/bin/sh 
    GIT_WORK_TREE=/var/www/project_name git checkout -f
    

    Update GIT_WORK_TREE, replacing /var/www/project_name with the root directory of your project (where you would normally upload the files using FTP).

    ProTip™ – You can add other 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:
    $ chmod +x hooks/post-receive
    

Setting Up Your Local Server

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

  1. Navigate to wherever your git repository is located:
    $ cd /var/www/project_name
    
  2. Add a remote source that references the server and repository we setup in the previous steps:
    $ git remote add production ssh://website.com/home/git/project_name.git
    

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

    ProTip™ – Add your username to the url so you don’t have to type it each time: ssh://username@website.com...

  3. 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 production +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 production 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.

Notes

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

Local Server

$ cd /var/www/project_name
$ git remote add production ssh://staging.website.com/home/git/project_name.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/*
...
Mike Everhart

Mike Everhart is a programmer, web developer, and owner of PlasticBrain Media LLC. He has a passion for startups and creating web-based applications to help them analyze, streamline, and automate their business processes. Mike has nearly 15 years of experience, and specializes in standards-based web design, programming, SEO, and SaaS.

13 Comments on "Using Git to Deploy Code"

  1. Working like a charm much thanks!

  2. cj says:

    This doesnt work for me.. I keep getting the error==>
    fatal: Not a git repository (or any of the parent directories): .git

    when I run this command==>
    git remote add prod username@website.com/pathtogit.git

    • Mike Everhart says:

      Hey CJ,

      You need to add “ssh://”:
      git remote add prod ssh://username@website.com/pathtogit.git

    • Mike Everhart says:

      It sounds like the path to your repository on the remote server is not correct. You need to use a full path name like /home/you/project_name.git. So that would give you something like:
      ssh://username@yoursite.com/home/you/project_name.git

      • cj says:

        Yep that’s what I tried. Here is the response:
        fatal: Not a git repository (or any of the parent directories): .git

        Ohhh I think I know what the error is. Does the folder on my local machine have to already be initialized for git?

      • cj says:

        Ok yeah I got that part working once i did it git init on my local but then I ran the

        git push production +master:refs/heads/master

        and got this error

        error: src refspec master does not match any.

        even though I ran a git status right before and it said I was on branch master

  3. cj says:

    Ok I figured it out after doing some googling and some stackoverflowing.

    Basically I can’t push an empty repo. So I ran these commands:

    touch README.md
    git add .
    git commit -m “initial commit”
    git push production +master:refs/heads/master

    and WHALA! It WORKED!

  4. cj says:

    Yep! thanks again for your post and help Mike. It really helped me get started on git. I was determined to start using git for my deployments to my personal website this weekend. I wanted to test it out and get things started. Thanks again.

  5. CJ says:

    One last thing. Since I was able to get my prod working now I am trying to set up the dev environment as a branch off of master. However when I run the command
    git push dev +dev:refs/heads/dev
    I get the error
    remote: you are on a branch yet to be born
    What does this mean and how can I correct it?

Got something to say? Go for it!