Using Git for Website Deployment
Update (11/7/15): I've tweaked this article to reflect my latest steps for setting up deployment via git.
After researching several alternatives, I finally implemented a git deployment process for my websites. I use Bitbucket private repos for a few personal websites (free!) and after a long time of SCP’ing code changes to my web host, it was time to make that process obsolete.
For each of my websites, I followed the steps at Arlo Carreon’s site to set up a second remote repo for git, to which I then push when I’m ready to deploy website changes. While the steps outlined were for those using Hostgaor, I’ve used this process on Bluehost, SiteGround, and 1&1 shared hosting and everything worked fine. Just make sure you have SSH access and git installed on your shared hosting.
Here’s the steps I took:
- On your local machine, set up a git repo for your project if you don't have one already. You can follow the Atlassian tutorial if needed. You should then push your latest project code to your chosen remote repository as well (ex. to Bitbucket or Github) so you have a copy of it outside of your own machine.
- Configure SSH access to your web host from your local machine using public key authentication. I already had this set up for all my SCP’ing activities, but you can find the steps on Ubuntu’s site. Once they key is generated on your machine, be sure to copy the public key (~/.ssh/.pub) over to your shared hosting account, creating the .ssh directory in your account home directory if it doesn’t exist already.
- SSH to your webhost and set up a new git repo, configuring it as a bare repo:
git init
git config core.bare true
After this is run, your project directory on your webhost should have a .git directory in it.
- Create a post-receive git hook by creating a post-receive file in your website’s newly created .git folder (/.git/hooks/post-receive). At the bottom of the file, include an “rm” line for directories and files that are part of your git repo but are not needed on the web host (like Grunt configs, Sass directories, etc):
#!/bin/sh
echo "********************"
echo "Post receive hook: Updating sheelahbgallery live website"
echo "********************"
work_tree=../
GIT_WORK_TREE=$work_tree git checkout -f
# Delete files not needed on web host
rm -Rf $work_tree/sass
rm $work_tree/package.json
rm $work_tree/Gruntfile.js
- Make sure the new post-receive hook script is executable by running:
chmod 755 <web-root>/.git/hooks/post-receive
- On your local machine, add your web host as a second remote. Your initial remote is your github (or for me, bitbucket) repo. By adding a second one pointing to your web host, you’ll be able to run
git push
and push changes live to your website at any time.
git remote add your-website user-name@your-domain.com:www/your-website
For Bluehost, my remote path took the form of user-name@box701.bluehost.com:/home4/user-name:~/www/mysite
.
- For your initial attempt, you may want to back up your site on your web host if it's there already. I’d recommend making a copy of your website directory on your host just in case something goes awry:
cd # Go to your web host home directory, one level up from your website root
cp -R your-website your-website-bk
- When you have changes to commit from your dev machine, push them to your web host after pushing to github or bitbucket:
git push # push to bitbucket or git
git push your-website master # master is only needed for the first push
When the push is done, you should see output like the following:
Enter passphrase for key '/home/sheelah/.ssh/bluehost':
Counting objects: 35, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (34/34), done.
Writing objects: 100% (35/35), 1.07 MiB | 0 bytes/s, done.
Total 35 (delta 1), reused 0 (delta 0)
remote: ********************
remote: Post receive hook: Updating sheelahbgallery live website on bluehost
remote: ********************
To bluehost:/home4/sheelahb/public_html/sheelahbgallery
* [new branch] master -> master
- Verify your website directory on your web host has the file updates. Also verify the directory and file permissions are correct (755 for directories and 644 for files, normally).
- Add an .htaccess file to your .git directory in your web root with the following content to make your .git directory not reachable on the web:
deny from all
You can also prevent access to all dot files using your .htaccess file if using Apache. See David Walsh’s blog post on HTML5 Boilerplate.
Note: If you have caching configured on your site (such as a caching plugin installed in WordPress), you'll need to empty the cache in order to view the updated site.
Additional Possibilities
As mentioned on Arlo Carreon’s site, you could configure a third remote repo pointing to a different directory on your web host to be used as a staging environment. This could be a place to verify changes before pushing to your live site.
You can also configure your git push
command to push to multiple repos at once.
For other git deployment alternatives, see Stack Overflow.