Twitter icon LinkedIn Icon Github Icon Stackoverflow Icon

Using Git to push to your production server

By: Roger Creasy

I have used Git for version management for several years. Recently I began using it to push code to both a web-accessible repository, as well as the server from which the code is served. Using this workflow, all I have to do to make code live is run   git push live . In this article, I will teach you the process I use.

Assumptions I Am Making

  • You already have at least a basic understanding of Git
  • Git is installed on both your development box and your production server (I will cover installing Git in a separate article)
  • You have passwordless ssh access to your server
  • Your project is managed with Git on your local development box

Setting Up the Server Side

Something that was new to me in this setup is that the repository is placed in a different directory than the project files. Your repo should be placed outside of your web-accessible structure. I chose to set my repository up in a directory at /srv/repos. Within that directory, I create a directory for each repo that is on the server. i.e. /srv/repos/mysite.git This directory needs to be writable by the user who has ssh access since that is the user who will be pushing files to the repo. For ease of managing the files, I make my ssh user the owner of the directory. Here are the commands assuming the ssh username is sshuser:

sudo mkdir -p /srv/repos/mysite.git
sudo chown -R sshuser /srv/repos/mysite.git

Alternatively, you could make your ssh user the member of a group. Then, make that group the group for the directory.

Next, we need to initialize Git. When you run git init or git clone you initialize git in a directory with a working directory. The Git structure for the repo is placed in a subdirectory, namely a .git directory.  A working directory is just that, a directory where we work on our files. For server management, we do not want a working directory. The live version of our site or application will not be actively changed like your local repo is. To set up a repository without a working directory add the --bare switch to the git init command run within the directory that will house the repo.

cd /srv/repos/mysite.git
git init --bare

Now we have a Git repo with no HEAD, and no working files.

Next, we need to add a post-receive Git hook. This hook is a bash script that is run each time a push is received. Don't worry if you don't know bash. It is a simple script. Name this script post-receive, and save it in the hooks directory within your repo directory structure. Continuing with our example, this location would be  /srv/repos/mysite.git/hooks . Here is an example script:

#!/bin/sh
GIT_WORK_TREE=/path/to/webroot/of/mywebsite
git checkout -f

For me, the path to my production files is usually  /var/www/mysite . I typically set the permissions on my production files to me as the owner, and a group to which my webserver belongs. Make sure that this directory already exists; it is not automatically created.  GIT_WORK_TREE  is exactly what it sounds like. It tells Git where to put the pushed files. The command  git checkout -f  checks out the pushed version. The switch  -f  is "force", which forces git to use the uploaded files. After writing this file, it needs to be made executable.

sudo chmod +x hooks/post-receive

That's it on the production server. Next, we need to set up our local development box.

Setting UP the Local Development Box

These instructions assume you already have a local Git repository set up. You can have a centralized cloud-based repository like Github, BitBucket, GitLab, etc.

We need to add our production server as a remote. Following the same format as our example above, this would be done with the code below.

git remote add live ssh://111.222.333.444/srv/repos/mywebsite.git

The remote can be by IP address, like the example above. Or, if DNS is set up, you can use the domain name. Make sure the path after the IP or domain match what you set up on the server.

On some servers, I use a different username than the one I work under on my development box. To overcome this issue, and for other conveniences, I use an SSH config file. If you are in this situation, the code above should be done like the code below. This is an alternative to the example above. Don't use both.

git remote add live ssh://username@host/srv/repos/mywebsite.git

In the above, "username" is the username set up in your SSH config file, and "host" is the host from that file. I'll write another post about SSH config files at some point.

Now, we are ready to push our files to production. Still following the format from our examples above, enter the code below.

git push live +master:refs/head/master

We have no need to push branches other than master to production. So, the command above tells Git to push only the master branch. Subsequent pushes, when we update the files, do not require the switch. To push updated files to production after testing, use the simple push below.

git push live

Conclusion

That's it. You now have an easy way to push code to your production server. If you enjoyed this post, or, if you have suggestions for improvements, please let me know. You can reach me via any of the methods in the footer. Hint: I always monitor Twitter and IRC.

Thanks for reading all the way to the end. This was not a short post.

Publication Date: 2018-05-29 00:49:40