Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git: Deploy only a directory from post-receive hook

Tags:

git

deployment

Having followed the instructions from this article I have a post-receive hook which currently reads:

#!/bin/sh
git --work-tree=/home/user/example.com --git-dir=/home/user/example.com.git checkout -f

This is working well - all the files and directories are getting deployed. However I'd like to only deploy the files from the Build folder within example.com.git (I'm using Hammer by the way.) so not all the development files are available and viewable on the live server.

Question: What do I alter/add to the above Git command in order to only checkout/deploy what's within the Build directory?

Update: After the discussion in the comments I came to the following, which works in my case.

#!/bin/sh
git --work-tree=/home/user/example.com --git-dir=/home/user/example.com.git checkout -f master -- Build/
cd /home/user/example.com
cp -rRp Build/. .
rm -rf Build
like image 270
Eystein Avatar asked Jan 11 '23 12:01

Eystein


2 Answers

I'll abbreviate the values supplied to --work-tree and --git-dir as WT and REPO respectively so that everything can fit without a horizontal scrollbar.

The general form should be:

#!/bin/sh
git --work-tree=WT --git-dir=REPO checkout -f -- paths

Suppose at the WT directory that's being deployed on the live server, you only want to checkout the Build folder in the repository. This becomes

#!/bin/sh
git --work-tree=WT --git-dir=REPO checkout -f -- Build

In general, you can replace the paths portion with one or more files in the git repository. These are specified as relative paths according to how they are placed in the repo. So if your git repo looks like this:

FolderOne
|- FolderTwo
|  |- FileOne
|- FolderThree

FolderFour
|- FileFive

And you want to checkout FileOne and everything FolderFour, you should do:

git --work-tree=WT --git-dir=REPO checkout -f -- FolderOne/FolderTwo/FileOne FolderFour

UPDATE:

It's been some time since I've dealt with Git hooks, but I think other than some details like their stdin and argv, you can put anything inside.

So for checking out everything in the Build folder but not the Build folder itself, you could do something like this in the post-receive hook:

git --work-tree=WT --git-dir=REPO checkout -f -- Build/
cd WT
cp -r Build/* .
rmdir Build

So we first checkout the Build directory into the WT directory. Then we cd into the WT directory, copy everything out from the Build directory using cp -r Build/* . . The . stands for the current directory, which is the WT directory we just cd into. Once that's done, we remove the now empty Build directory.

Hence, everything from the Build directory is now checked out into the WT directory, without the Build directory itself. Of course, you've got to replace WT and REPO by the actual paths to the work tree and git repository respectively.

Hope that helps

like image 59
yanhan Avatar answered Jan 19 '23 12:01

yanhan


yanhan's solution did not work for me.. here is my approach...

#!/bin/bash
TARGET="/htdocs/my-project/public"
TEMP="/htdocs/my-project/tmp"
PUBLIC="/htdocs/my-project/tmp/public"
GIT_DIR="/htdocs/my-project/test.git"
BRANCH="master"

while read oldrev newrev ref
do
    if [[ $ref = refs/heads/$BRANCH ]];
    then
        # create temp directory
        mkdir $TEMP
        # check out the master branch
        git --work-tree=$TEMP --git-dir=$GIT_DIR checkout -f 
        # remove current target files and directory
        rm -rf $TARGET
        # move contents of the chosen folder to the target 
        mv $PUBLIC $TARGET
        # delete the tmp directory since not needed anymore..
        rm -rf $TEMP
    fi
done
like image 23
mr.louis Avatar answered Jan 19 '23 11:01

mr.louis