Deploying Websites with Git on Dreamhost
Note: This article has been updated since it was first posted in March 2012.
For someone who version-controls with filenames, Git is amazing stuff. I had been using Git to just do the bare-minimum of version control on my local machine, but I thought this would be a good opportunity to explore Git and learn more. In this guide I’ll take you through using Git to publish a site to Dreamhost. I’m making the assumption that you already have your local site in a Git repo, and that you’re running OS X. Unix will likely use the same commands but Windows won’t, hopefully this can get you pointed in the right direction though.
Getting started
You’ll need to SSH into your Dreamhost server to perform some of the
setup, and luckily Dreamhost has a wiki
page about getting
that started. If you already have SSH access with a user, you can type
ssh user@server.dreamhost.com
into a terminal, and then enter your
password after the prompt.
Now that we’re on the server, we can see if Git is installed by running
which git
. If you see a path like /usr/bin/git
in the terminal then
you are good to go. If you don’t have Git on your server already,
Dreamhost has a wiki
page
to help you out (they have a pretty thorough wiki, including lots of
unofficial topics).
Setup the server
In your home folder on Dreamhost, we’re going to run some commands to set up the remote Git repo.
mkdir website.git && cd website.git
git init --bare
You should change website.git
to something more descriptive, I named
mine after the site’s domain that this is for: brandonevans.ca.git
.
Now that we have an empty repo set up, we need to use a Git hook so that
when we push our site to this remote repo it will get moved to the
folder it’s hosted from. This folder is probably the domain name of your
site, so the full path of mine is /home/brandonevans/brandonevans.ca
.
I use these in the example below. When you use the cat
command,
whatever you type next is going to be saved into the
hooks/post-receive
file. When you’re done typing everything from #!
(hash-bang) to checkout -f
, type control-d to save the file.
cat > hooks/post-receive
#!/bin/sh
git --work-tree=/home/brandonevans/brandonevans.ca --git-dir=/home/brandonevans/brandonevans.ca.git checkout -f
Once this file is created, run chmod +x hooks/post-receive
to allow
that file to be executed by the system. Now the remote hook is set
up, and we can tell our local repo how to send our files up to the
server. Exit the SSH session with exit
and navigate to
your site’s local directory on your computer.
Linking the repos
First we need to tell the local repo about the new remote repo we just
setup. Here we’re setting the name of the remote to web
, but you can
change that as you wish (production, staging, TUBES, etc.). Again,
you’ll want to put your own username and Git repo name into the command.
git remote add web ssh://brandonevans@server.dreamhost.com/home/brandonevans/brandonevans.ca.git
And now, we push! But first, realize that this will overwrite what is currently in your site’s public folder. Make sure anything you want is saved and committed in the local Git repo first, and backed up twice (never hurts).
git push web +master:refs/heads/master
If everything is working, you’ll see output like:
Counting objects: 30, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (17/17), done.
Writing objects: 100% (17/17), 5.16 KiB, done.
Total 17 (delta 11), reused 0 (delta 0)
To ssh://brandonevans@server.dreamhost.com/home/brandonevans/brandonevans.ca.git
1f92b40..757a17a master -> master
If you don’t see this you can try adding the remote repo with your own
url like: ssh://myuser@myowndomain.com/home/etc
Now go check out your site to make sure everything looks right.
Big files
When I first set this up, my site had a lot of large audio files hosted
on it. Because I’m on a shared server, these large files caused an issue
when the hook did the first checkout, as Dreamhost’s procwatch killed
git-checkout because of high resource usage. I was able to solve this
with some configuration changes using git config --global
and the
following settings:
pack.windowmemory=10m
pack.sizelimit=20m
pack.threads=1
pack.packsizelimit=60m
pack.deltacachsize=50m
core.packedgitwindowsize=50m
core.packedgitlimit=50m
core.deltacachesize=50m
core.repositoryformatversion=0
core.filemode=true
core.bare=true
I’ve since moved all large files to an S3 bucket, and I’d definitely recommend never storing large files in your Git repo. Having a small repo makes it so much easier for you or someone else to clone it.
Finale
And that’s it! For a basic website like I’m running, this knocks out the FTP step after I commit changes because Git already knows the changes that need to be pushed. It’s also really cool to see how powerful Git hooks can be. Two resources I used in researching this article were Pro Git and Abhijit Menon-Sen’s Using Git to manage a web site. If you have any questions or suggestions about this feel free to reach out on twitter: @interstateone.