416

Is it possible to deploy a website using git push? 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?

Nick Volynkin
  • 11,882
  • 6
  • 39
  • 62
Kyle Cronin
  • 72,761
  • 40
  • 144
  • 160
  • 2
    I'm guessing this would only apply in situations where there is only one production server, right? – Rijk Mar 13 '12 at 16:24
  • 6
    @Rijk Well, you can push to multiple servers simultaneously with Git, but once you get up to that level you might want an actual solution, not a hack like this. – Kyle Cronin Mar 13 '12 at 16:32
  • I have had success using [capistrano](http://en.wikipedia.org/wiki/Capistrano) with my projects, which although was originally designed for Ruby on Rails application deployment, works well with PHP and other projects. –  Jul 28 '12 at 07:56
  • Translated the answers into Russian on ru.so: http://ru.stackoverflow.com/questions/428483/git-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D0%B8-%D1%80%D0%B0%D0%B7%D0%B2%D0%B5%D1%80%D1%82%D0%BA%D0%B0-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0 – Nick Volynkin Jun 06 '15 at 22:15

19 Answers19

289

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 (in the answer below)

  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
    
Community
  • 1
  • 1
Kyle Cronin
  • 72,761
  • 40
  • 144
  • 160
  • 129
    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. – Jeff Ferland May 10 '10 at 21:41
  • 39
    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 Jun 08 '10 at 19:54
  • 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? – Eric Martindale Jun 23 '10 at 04:55
  • 3
    this link is dead. is there another link to the post-update file? – Robert Hurst Jul 27 '10 at 23:27
  • 1
    If you're using submodules, you may want to add `git submodule update --init --recursive` to the `post-update` script. – Eric Jan 02 '11 at 21:59
  • I like the idea of making the public directory a subdirectory. I think I may just make a symlink in my /var/www directory to the /public directory in my repo. – freedrull Feb 13 '11 at 21:48
  • I like it but the user you push with need to have right access to htdocs. It's certainly the git user. How do you manage that? You put git user in a www-pub group and give to this group a write permission in /path/htdoc/*? – gagarine Apr 05 '11 at 12:53
  • 6
    Maybe I'm missing something but wouldn't you want your production server(s) to **pull** from a master git repositories producttion branch. I guess the OP only has one server? I usually make my continuous integration server do the deployment of my site (running some tests before deploy). – Adam Gent Sep 16 '11 at 11:15
  • 4
    Following those steps from a repository that already has a sequence of commits; at first you can't push because the master branch is already checked out. Then if you checkout an alternative branch on the remote only the different files are checked out into the working directory. I expected the hook to do a reset --hard for me – barrymac Oct 12 '11 at 10:15
  • need to add one more step to allow pushing to remote, will add to the answer – barrymac Oct 12 '11 at 10:27
  • This does not play nicely with gitolite due to this line: die "$repo ends with a slash; I don't like that\n" if $repo =~ /\/$/; – olive Oct 20 '11 at 17:32
  • Maybe I am missing something, but it looks like after you push the code to production, you still have to git clone that bare .git repository before you can full deploy? So it is a two step process? – Antony Feb 26 '12 at 05:36
  • 1
    @Antony That's what the server side post-update hook is for - it takes care of that automatically upon push – Kyle Cronin Feb 26 '12 at 05:39
  • when sub-modules are used - they'll still contain .git - right? – Stann May 04 '12 at 18:40
  • 1
    if you're ssh port isn't 22, use this syntax : url = ssh://user@server:44000/home/fold/er/.git – Laurent Debricon Dec 12 '12 at 13:26
  • You should take a look at this very trivial solution : http://danbarber.me/using-git-for-deployment/ – Matthieu Lucas Jan 31 '13 at 04:45
  • If you meet _refusing to update checked out branch_ error you can resolve it by running `git config receive.denyCurrentBranch ignore` on server. – Kir Novak Nov 24 '15 at 08:04
81

Using the post-update file below:

  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 file below

  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
    
#!/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
BadPirate
  • 24,683
  • 10
  • 85
  • 118
  • 5
    Geez...just write this script on a language you use for development being it php, python, groovy or whatever! I never understood this love for shell scripts which have (subjectively) quite odd syntax and so little functional features. – dVaffection Nov 10 '14 at 04:55
  • 5
    @dVaffection in any case you are going to write shell commands if you are using git. so instead of writing a script in another language and constantly juggle between that language and shell. writing it all in shell seems logical don't you think ? – Abderrahmane TAHRI JOUTI Jan 14 '16 at 10:44
  • i had to perform 'git config receive.denyCurrentBranch updateInstead' on the server also, so that it would accept the push. I think its because the branch was checked out? – stackPusher Mar 30 '17 at 15:43
61

After many false starts and dead ends, I'm finally able to deploy website code with just "git push remote" thanks to this article.

The author's post-update script is only one line long and his solution doesn't require .htaccess configuration to hide the Git repo as some others do.

A couple of stumbling blocks if you're deploying this on an Amazon EC2 instance;

1) If you use sudo to create the bare destination repository, you have to change the owner of the repo to ec2-user or the push will fail. (Try "chown ec2-user:ec2-user repo.")

2) The push will fail if you don't pre-configure the location of your amazon-private-key.pem, either in /etc/ssh/ssh_config as an IdentityFile parameter or in ~/.ssh/config using the "[Host] - HostName - IdentityFile - User" layout described here...

...HOWEVER if Host is configured in ~/.ssh/config and different than HostName the Git push will fail. (That's probably a Git bug)

Earl Zedd
  • 1,066
  • 10
  • 10
  • I followed the steps in the article you mentioned, and everything worked like a charm. I only wonder wether there are some drawbacks concerning security or stability. Any advice on this? – xlttj Dec 06 '11 at 22:43
  • xl-t: Assuming you're using Git over SSH I'd say the danger lies in making a mistake with Git. You could ask the author of the article; he ends it with "Questions and suggestions are welcome." My current (brain-dead) replication strategy is to use Transmit by Panic Software. – Earl Zedd Dec 07 '11 at 17:21
  • 1
    The linked article has one important requirement when you use hooks. The hooks will fail if .git happens to be in the same naming scheme as working directory. i.e. /foo/bar (working directory) and /foo/bar.git (barebone git repository). So make sure you rename /foo/bar to something else, such as /foo/bar.live or /foo/blah Well, in case you are wondering, the exact error message you would receive if your working directory has the same name as the barebone repository is "remote: fatal: Could not jump back into original cwd: No such file or directory" – Antony Feb 26 '12 at 07:15
  • 1
    I don't follow why you would need a post-deploy hook to run. Pushing the code changes to a remote repo means the remote repo is up to date. What am I missing? – Charlie Schliesser Jun 29 '12 at 20:12
  • 1
    @CharlieS what you're missing is that git won't let you push a branch to a repository that has that branch checked out. In this case, the (IMHO very nice) answer is to have two repositories: a bare repo you push to and a second repo whose working directory is updated via the hook when the bare repo is pushed to. – Ben Hughes Feb 16 '13 at 10:27
  • Excellent answer. Much cleaner than anything else I've found – Ben Hughes Feb 16 '13 at 10:28
  • Easiest solution. This should be the highest voted and accepted answer. – Oliver Angelil Jul 06 '17 at 16:11
21

dont install git on a server or copy the .git folder there. to update a server from a git clone you can use following command:

git ls-files -z | rsync --files-from - --copy-links -av0 . user@server.com:/var/www/project

you might have to delete files which got removed from the project.

this copies all the checked in files. rsync uses ssh which is installed on a server anyways.

the less software you have installed on a server the more secure he is and the easier it is to manage it's configuration and document it. there is also no need to keep a complete git clone on the server. it only makes it more complex to secure everything properly.

Christian
  • 3,115
  • 24
  • 23
12

In essence all you need to do are the following:

server = $1
branch = $2
git push $server $branch
ssh <username>@$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.

Cody Gray
  • 222,280
  • 47
  • 466
  • 543
Lloyd Moore
  • 2,939
  • 28
  • 29
  • see my answer how to solve the problem if you need a different private key or user name for ssh – Karussell Nov 26 '11 at 16:22
  • This solution is faster than my own when deploying to multiple servers! Just push to main repo and pull in parallel from it. And if you don't want or can't deploy your keys to every instance use the key agent! `ssh -A ...` – Karussell Oct 31 '12 at 10:13
  • 1
    It would be easier if you included a guide on setting up SSH keys which this answer relies on to work 'seamlessly' – Hengjie Oct 31 '12 at 11:41
  • Use of `git pull` should be avoided for automated deployments because the merge part of it could require manual cleanup if there are any conflicts. – Quinn Comendant Apr 14 '15 at 00:37
12

git config --local receive.denyCurrentBranch updateInstead

Added in Git 2.3, this could be a good possibility: https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155

You set it on the server repository, and it also updates the working tree if it is clean.

There have been further improvements in 2.4 with the push-to-checkout hook and handling of unborn branches.

Sample usage:

git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead

cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git push origin master:master

cd ../server
ls

Output:

a
b

This does have the following shortcomings mentioned on the GitHub announcement:

  • Your server will contain a .git directory containing the entire history of your project. You probably want to make extra sure that it cannot be served to users!
  • During deploys, it will be possible for users momentarily to encounter the site in an inconsistent state, with some files at the old version and others at the new version, or even half-written files. If this is a problem for your project, push-to-deploy is probably not for you.
  • If your project needs a "build" step, then you will have to set that up explicitly, perhaps via githooks.

But all of those points are out of the scope of Git and must be taken care of by external code. So in that sense, this, together with Git hooks, are the ultimate solution.

  • To set it, run this command: 'git config receive.denyCurrentBranch updateInstead' in the terminal – stackPusher Mar 30 '17 at 15:44
  • 1
    This should be the most upvoted answer IMHO. It’s always so crazy to dig through all these answers with long shell script/hooks, if this **oneliner** can solve it **by just setting one git option**. – rugk May 06 '21 at 20:51
9

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
  • 828,234
  • 170
  • 1,097
  • 1,237
  • In case of error(s) in the new code, do you reset per commit or the entire pull? (Or is only 1 possible?) – Rudie Sep 27 '10 at 13:19
  • 1
    @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 Sep 27 '10 at 18:06
  • Just out of curiousity: why do you think hooks would be more trouble than it's worth for this? – Rijk Mar 13 '12 at 16:29
  • @Rijk: When using hooks for this, the actual web server docs directory is changed by an automatic background process. Logging in lets me have more control over exactly when changes are applied to the docs directory. Also, it's easier to fix when things go wrong. Hooks might be more appropriate if committers don't have sufficient access to log in to the web server. – Greg Hewgill Mar 13 '12 at 18:00
  • So your actual webapp folder is also a .git repository? What about the .git folder, it's visible to the outside world? – Fernando Jul 25 '14 at 15:31
  • @Fernando: In my case, yes, there's nothing secret in there. However, for many types of applications you may want to put the `.git` directory somewhere else (with `GIT_DIR` or `GIT_WORK_TREE`). – Greg Hewgill Jul 25 '14 at 20:16
  • Yes, thanks. It's simple to hide the .git via apache conf for example. – Fernando Jul 25 '14 at 20:28
5

We use capistrano for managing deploy. We build capistrano to deploy on a staging server, and then running a rsync with all of ours server.

cap deploy
cap deploy:start_rsync (when the staging is ok)

With capistrano, we can made easy rollback in case of bug

cap deploy:rollback
cap deploy:start_rsync
PiTheNumber
  • 20,216
  • 13
  • 96
  • 165
Supernini
  • 531
  • 5
  • 8
5

For Deployment Scenario

In our scenario we're storing the code on github/bitbucket and want to deploy to live servers. In this case the following combination works for us (that is a remix of the highly upvoted answers here):

  1. Copy over your .git directory to your web server
  2. On your local copy git remote add live ssh://user@host:port/folder
  3. On remote: git config receive.denyCurrentBranch ignore
  4. On remote: nano .git/hooks/post-receive and add this content:

    #!/bin/sh GIT_WORK_TREE=/var/www/vhosts/example.org git checkout -f

  5. On remote: chmod +x .git/hooks/post-receive

  6. Now you can push there with git push live

Notes

  • This solution works with older git versions (tested with 1.7 and 1.9)
  • You need to make sure pushing to github/bitbucket first, so you'll have a consistent repo on live
  • If your .git folder is within document root make sure you hide it from the outside by adding to .htaccess (source):

    RedirectMatch 404 /\..*$

Attila Fulop
  • 6,055
  • 2
  • 39
  • 45
5

Update: I'm now using Lloyd Moore solution with the key agent ssh -A .... Pushing to a main repo and then pulling from it in parallel from all your machines is a bit faster and requires less setup on those machines.


Not seeing this solution here. just push via ssh if git is installed on the server.

You'll need the following entry in your local .git/config

[remote "amazon"]
    url = amazon:/path/to/project.git
    fetch = +refs/heads/*:refs/remotes/amazon/*

But hey, whats that with amazon:? In your local ~/.ssh/config you'll need to add the following entry:

Host amazon
    Hostname <YOUR_IP>
    User <USER>
    IdentityFile ~/.ssh/amazon-private-key

now you can call

git push amazon master
ssh <USER>@<YOUR_IP> 'cd /path/to/project && git pull'

(BTW: /path/to/project.git is different to the actual working directory /path/to/project)

Karussell
  • 16,303
  • 14
  • 88
  • 188
2

Giddyup are language-agnostic just-add-water git hooks to automate deployment via git push. It also allows you to have custom start/stop hooks for restarting web server, warming up cache etc.

https://github.com/mpalmer/giddyup

Check out examples.

Artur Bodera
  • 1,631
  • 21
  • 20
1

My take on Christians solution.

git archive --prefix=deploy/  master | tar -x -C $TMPDIR | rsync $TMPDIR/deploy/ --copy-links -av username@server.com:/home/user/my_app && rm -rf $TMPDIR/deploy
  • Archives the master branch into tar
  • Extracts tar archive into deploy dir in system temp folder.
  • rsync changes into server
  • delete deploy dir from temp folder.
Community
  • 1
  • 1
Priit
  • 403
  • 1
  • 5
  • 15
1

I am using the following solution by toroid.org, which has a simpler hook script.

on the server:

$ mkdir website.git && cd website.git
$ git init --bare
Initialized empty Git repository in /home/ams/website.git/

and install the hook on the server:

$ mkdir /var/www/www.example.org
$ cat > hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/var/www/www.example.org git checkout -f
GIT_WORK_TREE=/var/www/www git clean -f -d # clean directory from removed files

$ chmod +x hooks/post-receive

on your client:

$ mkdir website && cd website
$ git init
Initialized empty Git repository in /home/ams/website/.git/
$ echo 'Hello, world!' > index.html
$ git add index.html
$ git commit -q -m "The humble beginnings of my web site."

$ git remote add web ssh://server.example.org/home/ams/website.git
$ git push web +master:refs/heads/master

then to publish, just type

$ git push web

There is a full description on the website: http://toroid.org/ams/git-website-howto

RusAlex
  • 7,639
  • 5
  • 32
  • 43
Synox
  • 1,120
  • 2
  • 14
  • 36
1

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
  • 1,988
  • 1
  • 19
  • 37
1

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
  • 1,171
  • 8
  • 11
1

As complementary answer I would like to offer an alternative. I'm using git-ftp and it works fine.

https://github.com/git-ftp/git-ftp

Easy to use, only type:

git ftp push

and git will automatically upload project files.

Regards

manuelbcd
  • 2,342
  • 1
  • 21
  • 32
0

I ended up creating my own rudimentary deployment tool which would automatically pull down new updates from the repo - https://github.com/jesalg/SlimJim - Basically it listens to the github post-receive-hook and uses a proxy to trigger an update script.

jesal
  • 7,044
  • 5
  • 47
  • 51
0

I use two solutions for post-receive hook:

DEPLOY SOLUTION 1

#!/bin/bash 
#  /git-repo/hooks/post-receive - file content on server (chmod as 755 to be executed)
# DEPLOY SOLUTION 1 

    export GIT_DIR=/git/repo-bare.git
    export GIT_BRANCH1=master
    export GIT_TARGET1=/var/www/html
    export GIT_BRANCH2=dev
    export GIT_TARGET2=/var/www/dev
    echo "GIT DIR:  $GIT_DIR/"
    echo "GIT TARGET1:  $GIT_TARGET1/"
    echo "GIT BRANCH1:  $GIT_BRANCH1/"
    echo "GIT TARGET2:  $GIT_TARGET2/"
    echo "GIT BRANCH2:  $GIT_BRANCH2/"
    echo ""

    cd $GIT_DIR/

while read oldrev newrev refname
do
    branch=$(git rev-parse --abbrev-ref $refname)
    BRANCH_REGEX='^${GIT_BRANCH1}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET1/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        git checkout -f $branch
    fi

    BRANCH_REGEX='^${GIT_BRANCH2}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET2/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        git checkout -f $branch
    fi
done

DEPLOY SOLUTION 2

#!/bin/bash 
#  /git-repo/hooks/post-receive - file content on server (chmod as 755 to be executed)
# DEPLOY SOLUTION 2

    export GIT_DIR=/git/repo-bare.git
    export GIT_BRANCH1=master
    export GIT_TARGET1=/var/www/html
    export GIT_BRANCH2=dev
    export GIT_TARGET2=/var/www/dev
    export GIT_TEMP_DIR1=/tmp/deploy1
    export GIT_TEMP_DIR2=/tmp/deploy2
    echo "GIT DIR:  $GIT_DIR/"
    echo "GIT TARGET1:  $GIT_TARGET1/"
    echo "GIT BRANCH1:  $GIT_BRANCH1/"
    echo "GIT TARGET2:  $GIT_TARGET2/"
    echo "GIT BRANCH2:  $GIT_BRANCH2/"
    echo "GIT TEMP DIR1:  $GIT_TEMP_DIR1/"
    echo "GIT TEMP DIR2:  $GIT_TEMP_DIR2/"
    echo ""

    cd $GIT_DIR/

while read oldrev newrev refname
do
    branch=$(git rev-parse --abbrev-ref $refname)
    BRANCH_REGEX='^${GIT_BRANCH1}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET1/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        # DEPLOY SOLUTION 2: 
        cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR1; 
        export GIT_WORK_TREE=$GIT_TEMP_DIR1/.
        git checkout -f $branch
        export GIT_WORK_TREE=$GIT_TARGET1/.
        rsync $GIT_TEMP_DIR1/. -v -q --delete --delete-after -av $GIT_TARGET1/.
        rm -rf $GIT_TEMP_DIR1
    fi

    BRANCH_REGEX='^${GIT_BRANCH2}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET2/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        # DEPLOY SOLUTION 2: 
        cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR2; 
        export GIT_WORK_TREE=$GIT_TEMP_DIR2/.
        git checkout -f $branch
        export GIT_WORK_TREE=$GIT_TARGET2/.
        rsync $GIT_TEMP_DIR2/. -v -q --delete --delete-after -av $GIT_TARGET2/.
        rm -rf $GIT_TEMP_DIR2
    fi
done

Both solutions are based on earlier solutions available in this thread.

Note, the BRANCH_REGEX='^${GIT_BRANCH1}.$' filters for the branch names matching "master" or "dev*" string, and deploys the work tree, if the pushed branch matches. This makes possible to deploy a dev version and master version to different places.

DEPLOY SOLUTION 1 removes only files, which are part of the repo, and was removed by a commit. It is faster than Deployment Solution 2.

DEPLOY SOLUTION 2 has the advantage, that it will remove any new files from the production directory, which was added on server side, no matter if it was added to the repo or not. It will be always clean dupe of the repo. It is slower than Deployment Solution 1.

klor
  • 953
  • 3
  • 9
  • 25
0

Given an environment where you have multiple developers accessing the same repository the following guidelines may help.

Ensure that you have a unix group that all devs belong to and give ownership of the .git repository to that group.

  1. In the .git/config of the server repository set sharedrepository = true. (This tells git to allow multiple users which is needed for commits and deployment.

  2. set the umask of each user in their bashrc files to be the same - 002 is a good start

Lloyd Moore
  • 2,939
  • 28
  • 29