Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Atomic website update with Git

I'd like to update a live website in an atomic way. If we've made several changes to pages, images, and javascript, all of the changes should appear simultaneously with no downtime, inconsistency, or 404s.

If I simply copy the changed files into the website directory, then at least a few requests will see an inconsistent site. If I copy the new site to a separate directory, then rename the old directory to take it out of production and rename the new directory to make it live, then for one brief moment we'll get 404s.

I really have two questions:

How can I update a directory of files in an atomic way?

How can I coordinate this with Git? We'd like to deploy using a git pull (or possibly push). The path of the site within the git repo is different from the path on the server, so a bit of moving/renaming needs to happen, either using git commands or OS commands.

like image 438
ccleve Avatar asked Jan 21 '13 16:01

ccleve


People also ask

Is git pull Atomic?

The answer is a very loud no: it's not atomic in any way. Individual files written in the work-tree are written one at a time, using OS-level write calls, which are not atomic.

What is atomic push git?

The --atomic option guarantees that either all three references will be updated on the remote, or none of them will. Please note that git push --atomic is still somewhat experimental, and it is possible to experience partial updates if you try to push something unusual.


1 Answers

You can do what you're imagining using symlinks. Moving one symlink over another is an atomic operation, so you should be able to avoid any 404 errors.

Your hook would deploy your site to a directory, perhaps named after the commit hash. Then it would make a symlink to that, perhaps called staging. Then it would move that symlink over the production symlink.

hash=`git rev-parse HEAD`
git checkout-index -a -f --prefix=/srv/www/$hash/
ln -s /srv/www/$hash /srv/www/staging
mv -T /srv/www/staging /srv/www/production

The -T argument is the short form for --no-target-directory, which is a part of GNU mv and prevents it from moving the source into the destination. Read more about target directories.

like image 76
Jason Owen Avatar answered Oct 13 '22 17:10

Jason Owen