views:

7438

answers:

6

How can I deploy a PHP website using Git? I have a hunch it has something to do with using git hooks to perform a git reset --hard on the server side, but how would I go about accomplishing this?

+2  A: 

The way I do it is I have a bare Git repository on my deployment server where I push changes. Then I log in to the deployment server, change to the actual web server docs directory, and do a git pull. I don't use any hooks to try to do this automatically, that seems like more trouble than it's worth.

Greg Hewgill
In case of error(s) in the new code, do you reset per commit or the entire pull? (Or is only 1 possible?)
Rudie
@Rudie: If you need to roll back changes on the deployment server, then you can use `git reset` to move back among the *latest* changes (all commits, not just the whole pull). If you need to roll back something specific that's not the latest commit, then you can use `git revert` but that should probably be used in emergencies only (`git revert` creates a new commit that undoes the effect of some previous commit).
Greg Hewgill
+1  A: 

Sounds like you should have two copies on your server. A bare copy, that you can push/pull from, which your would push your changes when you're done, and then you would clone this into you web directory and set up a cronjob to update git pull from your web directory every day or so.

Flame
A: 

You could conceivably set up a git hook that when say a commit is made to say the "stable" branch it will pull the changes and apply them to the PHP site. The big downside is you won't have much control if something goes wrong and it will add time to your testing - but you can get an idea of how much work will be involved when you merge say your trunk branch into the stable branch to know how many conflicts you may run into. It will be important to keep an eye on any files that are site specific (eg. configuration files) unless you solely intend to only run the one site.

Alternatively have you looked into pushing the change to the site instead?

For information on git hooks see the githooks documentation.

Chealion
+42  A: 

I found this script on this site and it seems to work quite well.

  1. Copy over your .git directory to your web server
  2. On your local copy, modify your .git/config file and add your web server as a remote:

    [remote "production"]
        url = username@webserver:/path/to/htdocs/.git
    
  3. On the server, replace .git/hooks/post-update with this file (mirror in so)

  4. Add execute access to the file (again, on the server):

    chmod +x .git/hooks/post-update
    
  5. Now, just locally push to your web server and it should automatically update the working copy:

    git push production
    
Kyle Cronin
Make sure you have a .htaccess policy that protects the .git directory from being read. Somebody who feels like URL diving could have a field day with the entire source code if it's accessible.
Autocracy
Alternatively just make the public directory a subdirectory of the git repo. Then you can have private files you can be sure won't be made public.
tlrobinson
I'm not sure that I understand this. Where should I create my first git repo, on the production web server or on the test web server?
Martindale
this link is dead. is there another link to the post-update file?
Robert Hurst
+1  A: 

In essence all you need to do are the following: server = $1 branch = $2 git push $server $branch ssh @$server "cd /path/to/www; git pull"

I have those lines in my application as an executable called deploy.

so when I want to do a deploy I type ./deploy myserver mybranch

Lloyd Moore
+5  A: 

Hi,

For all of those looking for the post-update file, here it goes:

#!/bin/sh
#
# This hook does two things:
#
#  1. update the "info" files that allow the list of references to be
#     queries over dumb transports such as http
#
#  2. if this repository looks like it is a non-bare repository, and
#     the checked-out branch is pushed to, then update the working copy.
#     This makes "push" function somewhat similarly to darcs and bzr.
#
# To enable this hook, make this file executable by "chmod +x post-update". 
git-update-server-info 
is_bare=$(git-config --get --bool core.bare) 
if [ -z "$is_bare" ]
then
      # for compatibility's sake, guess
      git_dir_full=$(cd $GIT_DIR; pwd)
      case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac
fi 
update_wc() {
      ref=$1
      echo "Push to checked out branch $ref" >&2
      if [ ! -f $GIT_DIR/logs/HEAD ]
      then
             echo "E:push to non-bare repository requires a HEAD reflog" >&2
             exit 1
      fi
      if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null)
      then
             wc_dirty=0
      else
             echo "W:unstaged changes found in working copy" >&2
             wc_dirty=1
             desc="working copy"
      fi
      if git diff-index --cached HEAD@{1} >/dev/null
      then
             index_dirty=0
      else
             echo "W:uncommitted, staged changes found" >&2
             index_dirty=1
             if [ -n "$desc" ]
             then
                   desc="$desc and index"
             else
                   desc="index"
             fi
      fi
      if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ]
      then
             new=$(git rev-parse HEAD)
             echo "W:stashing dirty $desc - see git-stash(1)" >&2
             ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT
             git-update-ref --no-deref HEAD HEAD@{1}
             cd $GIT_WORK_TREE
             git stash save "dirty $desc before update to $new";
             git-symbolic-ref HEAD "$ref"
             )
      fi 
      # eye candy - show the WC updates :)
      echo "Updating working copy" >&2
      (cd $GIT_WORK_TREE
      git-diff-index -R --name-status HEAD >&2
      git-reset --hard HEAD)
} 
if [ "$is_bare" = "false" ]
then
      active_branch=`git-symbolic-ref HEAD`
      export GIT_DIR=$(cd $GIT_DIR; pwd)
      GIT_WORK_TREE=${GIT_WORK_TREE-..}
      for ref
      do
             if [ "$ref" = "$active_branch" ]
             then
                   update_wc $ref
             fi
      done
fi

Alternatively, you may find it in Google's cache:

http://webcache.googleusercontent.com/search?q=cache:yNTUFsYBYFMJ:utsl.gen.nz/git/post-update+http://utsl.gen.nz/git/post-update&cd=1&hl=en&ct=clnk&gl=ie

Darío Javier Cravero