Erick Engelhardt
Erick Engelhardt

Reputation: 734

How to copy a pushed branch to another directory?

I have a branch called master (Production) and another called development. When I push a commit from master, the post-receive hook executes:

git --work-tree=/var/www/mywebsite.com --git-dir=/var/repo/mywebsite.com.git checkout -f

And the website is live. But I want my development branch copied to /var/www/mywebsite.com.dev .

Upvotes: 3

Views: 115

Answers (1)

Matthieu Moy
Matthieu Moy

Reputation: 16547

What you're trying to do by hand is what tools like Capistrano are meant for, and they will do it better (for example, your version is not atomic so your website has a mix of old/new files for a while, while capistrano will check out your tree in a directory, and then point a symlink to it, which is atomic).

If you stay with "git checkout", then "git checkout development" will checkout the development branch, so you want to execute this command when you receive a ref update on development. The script would go along the lines of:

#!/bin/sh

while read old new refname
do
    case "$refname" in
        refs/heads/master)
            git --work-tree=/var/www/mywebsite.com --git-dir=/var/repo/mywebsite.com.git checkout -f
            ;;
        refs/heads/development)
            git --work-tree=/var/www/mywebsite.com.dev --git-dir=/var/repo/mywebsite.com.git checkout -f refs/heads/development
            ;;
    esac
done

Now, we can improve the script in several ways:

  • Actually, since the hook receives the new ref value, you don't even need the branch name, and can use $new instead (more robust in case there are several ref updates close to each other in time).

  • For efficiency we can maintain one index file per checkout (so that unmodified files do not need to be actually checked-out)

  • The --git-dir option can be dropped, since we're checking out from the current directory (the hook is executed within the repository).

The improved script is:

#!/bin/sh

while read old new refname
do
    case "$refname" in
        refs/heads/master)
            GIT_INDEX_FILE="$PWD"/index.master git --work-tree=/tmp/www/mywebsite.com checkout -f $new
            ;;
        refs/heads/development)
            GIT_INDEX_FILE="$PWD"/index.development git --work-tree=/tmp/www/mywebsite.com.dev checkout -f $new
            ;;
    esac
done

On a related subject, you can also look at the new updateInstead value for receive.denyCurrentBranch introduced in Git 2.3. See for example the "Push to deploy" section on https://github.com/blog/1957-git-2-3-has-been-released

Upvotes: 1

Related Questions