0

I recently have started using Git in my daily workflow and I really love working with it.

I have a bare online repo (git init --bare --shared) sitting on my VPS under a folder called website.git and push pull changes to it from local whenever I need to, which works absolutely fine. Now, when I save data on my local repo, I push the changes online, but then I have to manually move the files into the public_html folder too, which as you can imagine, is a real pain.

I have tried using git hooks as described in http://toroid.org/ams/git-website-howto, but it's the permissions that are not working for me.

Both the public_html and website.git folders are owned by www-data:developers, but when the post-receive hook kicks in, it can't unlink the old files, and any new files are automatically owned by jack:jack which is the user I SSH into the server with.

My hooks/post-receive file is executable and contains:

#!/bin/sh
GIT_WORK_TREE=/home/web/website.com/public_html git checkout -f

And my online repo is stored in

/home/web/website.com/website.git

What am I doing wrong?

Goonyan Harir
  • 193
  • 1
  • 1
  • 9

2 Answers2

1

This is a basic operating-system permissions problem: when you use ssh to push changes, git uses ssh to connect to the remote host (as some user of your choosing—this is why the url allows ssh://user@host/path) so as to run the commands on the host that pick up the objects (commits, trees, blobs, and/or tags) being pushed and insert them into the target repo. Whoever that user is, is then also running the hooks. So when the post-receive hook runs, it's run as that user.

You could make the public_html directory more write-able (so that all your git push users can write to it); you could ssh in as user www-data; or you could use a set-uid program to make the git checkout -f run as the www-data user, with all the usual dangers of any set-uid program. (The sudo command can be used for that last technique. You'll want sudo -n -u www-data in the hook, I think, although I have never actually set this sort of thing up.)


Note: I experimented a bit and had an old (1.7.0.3) version of git on the target host. This has a bug where relative paths fail. To work around it, here is what I ended up with in hooks/post-receive (note, this is quite primitive as it does not check what was pushed-to):
#! /bin/sh
umask 0 # let everyone have write permission on everything
export GIT_DIR=$(readlink -f $(git rev-parse --git-dir))
export GIT_WORK_TREE=$(readlink -f /tmp/t)
(cd $GIT_WORK_TREE && git checkout -f)

In a newer git (with the bugs fixed) you won't need all of the above (although it does make the hook work when run manually, which is convenient).

torek
  • 330,127
  • 43
  • 437
  • 552
  • Thanks for the info. You're right, it is a permissions issue! I set the public_html folder to 777, that way all users can write to it, modified a file, and then performed a push. No errors were present, and the files in public_html changed owners from www-data to jack (which as you say would since jack is running the hook), the files changed to 755 too, and when I opened one of the changed files, it still hadn't updated! I wonder how other people get this to work...? – Goonyan Harir May 10 '12 at 14:28
  • Hm. If you're willing to have everything be very write-able, try adding `umask 0` before doing `git checkout -f`. Also, due to a bug fixed in git 1.7.4 I had to make sure that all paths were always absolute and that I did a "cd" to $GIT_WORK_TREE; see edit to answer. – torek May 11 '12 at 05:35
0

I had a permission issue similar to your and used another technique to do the deployment, but I did change my apache to use my git user. It is working for me on git 1.7.9 and Ubuntu 12.04.1 LTS with Apache/2.2.22.

My git user is called git and my apache used the ubuntu user. I had to edit the apache configuration on /etc/apache2/conf.d/security (you can do it on /etc/apache2/http.conf also) to include:

User git
Group git

Now my /var/www/myproject deploys all the files on push, creating the files with git:git user/group and my apache uses the same user/group to run.

You can always add this to the end of yur hooks/post-receive script:

chown -R www-data:developers /home/web/website.com/public_html

Now you just have to restart your server or do a service apache2 restart

Community
  • 1
  • 1
Alexandre Marcondes
  • 5,428
  • 2
  • 22
  • 31