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.
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 email@example.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
to help you out (they have a pretty thorough wiki, including lots of
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:
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
I use these in the example below. When you use the
whatever you type next is going to be saved into the
hooks/post-receive file. When you’re done typing everything from
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://firstname.lastname@example.org/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://email@example.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
Now go check out your site to make sure everything looks right.
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
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.
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.