【问题标题】:How can I automagically make a checkout upon push?如何在推送时自动结帐?
【发布时间】:2013-02-04 06:56:34
【问题描述】:

考虑以下情况:

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

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

【问题讨论】:

  • 所以你有一个像 /git/foo.git 这样的 git 存储库,当你推送到 production 分支时,你希望你的网络服务器的 git 存储库位于 /var/www/ foo 来拉取你的新提交?
  • @tewe 是的。但在 /var/www/foo 处不必有 git 存储库。如果 /var/www/foo 只包含一个结帐也没关系。
  • 那么你必须在某个地方有一个中间存储库,我不认为你可以在没有 git 存储库的情况下结帐,并且你不能让另一个非裸露的,因为那样你就不能推送到 production 分支(如果它已在那里签出)。
  • @tewe 我记得可以将(裸)存储库的特定版本检出到任意目录中。
  • 顺便说一句,如果你把我的答案和@Jacob 结合起来,你就会得到你想要的。

标签: git githooks


【解决方案1】:

您必须使用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. 您可以在不中断当前部署的情况下执行解包后程序,例如编译或安装依赖项

提示

  1. 每次更新,附加到一个部署日志,说明更新发生的时间,以及它们的哈希 ID 是什么。这使得回滚非常更容易。

【讨论】:

  • 如何签出到任意目录?我需要传递给 git checkout 的选项是什么?
【解决方案2】:

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

#!/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

【讨论】:

  • 你可以将参数--work-tree=/var/www/foo添加到--git-dir旁边的git pull命令中,而不是cd /var/www/foo
【解决方案3】:

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

git archive | tar x dir

【讨论】:

  • 啊,是的,当然,我什至在对我的回答的评论中写了这个:) 没想到这样。
猜你喜欢
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
  • 2012-05-20
  • 2011-04-19
  • 2023-01-12
  • 1970-01-01
  • 1970-01-01
  • 2011-09-23
相关资源
最近更新 更多