3

我在我的服务器上创建了一个裸 git repo,并从这个博客设置了以下 post-receive 钩子:

#!/bin/bash

while read oldrev newrev ref
do
  branch=`echo $ref | cut -d/ -f3`

  if [ "master" == "$branch" ]; then
    git --work-tree=/path/to/my/project/live/ checkout -f $branch
    echo 'Changes pushed live.'
  fi

  if [ "develop" == "$branch" ]; then
    git --work-tree=/path/to/my/project/dev/ checkout -f $branch
    echo 'Changes pushed to dev.'
  fi
done

这样每当我在本地推送到我的服务器时,更改都会自动发布到每个分支的文件夹中,而无需手动拉取。

我设置了正确的权限以同时使用 dev 文件夹:

drwxrwsr-x 2 git git 4096 Sep 29 12:10 live/
drwxrwsr-x 2 git git 4096 Sep 29 12:09 dev/

并且从开发分支推送按预期工作。当我签出主分支并进行合并时会出现问题。当我推送主文件时,新文件被复制到我服务器上的活动文件夹中,但我在本地删除的文件没有被删除。

如何让 post-receive 正确更新 live 文件夹?谢谢!

4

2 回答 2

4

我遇到了同样的问题。正在研究 rsync 以将 tmp 文件夹文件复制到 live 文件夹,但后来我想为什么不在工作树上使用 git glean 。

我不确定这是否会很糟糕,但它应该只从文件夹中删除未跟踪的文件,并使用您的 .gitignore 设置来不删除不在您的存储库中的文件。

它似乎完成了我想要的,即清除未通过推送删除的剩余文件。

#!/bin/sh
while read oldrev newrev refname
do
    branch=$(git rev-parse --symbolic --abbrev-ref $refname)
    if [ "master" == "$branch" ]; then
        GIT_WORK_TREE=/home/store/public_html git checkout -f master
        GIT_WORK_TREE=/home/store/public_html git clean -fd
    fi
    if [ "test" == "$branch" ]; then
        GIT_WORK_TREE=/home/store/test_html git checkout -f test
        GIT_WORK_TREE=/home/store/test_html git clean -fd
    fi
    if [ "dev" == "$branch" ]; then
        GIT_WORK_TREE=/home/store/dev_html git checkout -f dev
        GIT_WORK_TREE=/home/store/dev_html git clean -fd
    fi
done
于 2015-11-27T17:02:51.140 回答
3

问题是 git 不知道要删除什么(它在工作树中没有索引,跟踪这些事情)。应该可以使用每个工作树的索引来解决这个问题,但我认为只git checkout -f进入一个新的空目录,然后重命名新目录和旧目录以使新版本“上线”更简单。这也缩小了竞争条件窗口:现在没有版本时只有一个短暂的时刻(mv操作之间) ,而不是旧版本和新版本混合时的稍长的窗口(期间)。checkout

master注意:如果有一个名为or的标签,那么您显示的脚本将会出错,develop因为这两个标签分别是refs/tags/masterrefs/tags/develop。我建议通过 shell 函数和case语句解决这个问题(如果你关心:-)),以减少非部署情况下的进程生成,例如:

die() {
    echo "$@" >&2
    exit 1
}

# deploy (to given path, $1) the version named by $2
# if the target is /some/path/there we use a temp version
# named /some/path/tmp.<pid> to hold the new one until we
# can swap it out, and $1.old.<pid> while we remove the old.
deploy() {
    local path=$1 branch=$2
    local tmpdir=${path%/*}/tmp.$$        # tune this as needed

    echo "deploying $branch to $path via $tmpdir..."
    trap "rm -rf $tmpdir" 0 1 2 3 15
    mkdir $tmpdir || die "can't create work dir $tempdir"
    git --work-tree=$tmpdir/ checkout -f $branch
    mv $path $path.old.$$ ||
        die "unable to move live version out of the way"
    mv $tmpdir $path ||
        die "unable to set new version live"
    trap - 0 1 2 3 15
    echo "done, cleaning up old version"
    rm -rf $path.old.$$
}

while read oldrev newrev ref; do
    case $ref in
    refs/heads/master) deploy /path/to/my/project/live master;;
    refs/heads/develop) deploy /path/to/my/project/dev develop;;
    esac
done

(注:完全未经测试)。

于 2013-09-29T10:06:34.377 回答