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
$ 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
$ 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
$ git remote add production ssh://firstname.lastname@example.org/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
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):
$ 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
$ 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
$ 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
$ cd /var/www/html/project_name $ git remote add staging ssh://email@example.com/var/www/site.com/git/staging.git $ git push staging +staging:refs/heads/staging
$ git push staging staging
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://firstname.lastname@example.org/home/git/project_name.git fetch = +refs/heads/*:refs/remotes/production/* ...
ERRORS & SOLUTIONS
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://email@example.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.