Atomic website update with Git

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.