如何在推送时自动进行结账?

时间:2013-02-02 22:18:42

标签: git githooks

考虑以下情况:

我有一个包含javascript项目代码的git存储库foo.git。在此存储库中有一个分支 production ,其中包含由Web服务器提供的代码状态,该服务器从/var/www/foo获取代码。此存储库是项目的主存储库。每个人都推着/拉出它。

每当有人推送到特定分支时,是否可以将/var/www/foo更新为 production 的结帐?您可以假设git守护程序(或用户所有人登录以通过SSH连接的用户git)有权写入所述目录。

3 个答案:

答案 0 :(得分:2)

您必须使用git init --bare在服务器上创建一个裸存储库。 然后使用post-receive挂钩来触发部署。 您的部署方式取决于您。

我的部署策略

我通常会放置一个deploy导演,在某个地方合乎逻辑。 然后每次结账时,我将最新的分支解压缩到deploy/COMMIT_ID,其中COMMIT_ID是最新推送的散列。结帐完成后,您可以将符号链接重新指向最新的部署目录。

我通常的目录结构:

deploy.git/
deploy/
    a7922231/
    b2f0a2af/
    latest -> b2f0a2af 

解压缩更新

我通常使用git-checkout将分支解压缩到目录中,而不是使用git-archive

# Assuming current directory is deploy.git
HEAD=`cat refs/heads/master`
mkdir -p ../deploy/${HEAD}
git archive master | tar -x -C ../deploy/${HEAD}

您的网络服务器可以指向deploy/latest,更新将或多或少是原子的。

我经常在制作中使用它,并且比在同一目录中解压缩有一些好处。

  1. 回滚很容易
  2. 您可以执行post-unpack程序,例如编译或安装依赖项,而不会中断当前部署
  3. 提示

    1. 每次更新,附加到部署日志,说明更新何时发生,以及他们的哈希ID是什么。这使回滚更多更容易。

答案 1 :(得分:1)

您必须在post-receive中创建一个名为/git/foo.git/hooks directory的文件(基于我上面的评论)。像这样(有一些调试日志):

#!/bin/sh

echo 'Hook called'
pullneeded=false

while read oldrev newrev refname
do
    echo "OLDREV $oldrev NEWREV $newrev REFNAME $refname"
    if [ "$refname" == "refs/heads/production" ]; then
        echo 'Pull needed'
        pullneeded=true
    fi
done

if [ $pullneeded ]; then
    echo 'Pull'
    cd /var/www/foo
    git --git-dir=/var/www/foo/.git pull
fi

echo 'Hook done'

您必须在/var/www/foo设置git存储库以跟踪其他存储库的 production 分支。如果它被称为 origin 那么它就是:

git branch --set-upstream production origin/production

当然, production 分支必须在/var/www/foo存储库中签出。

<强>已更新

也许post-update挂钩更合适(样本来自此处https://stackoverflow.com/a/6597728/299788):

#!/bin/bash    

case " $* " in
*' refs/heads/production '*)
    cd /var/www/foo
    git --git-dir=/var/www/foo/.git pull
    ;;
esac

答案 2 :(得分:0)

您可以使用以下命令将git存储库foo.git签出到目录dir中:

git archive | tar x dir