【问题标题】:Git for Websites / post-receive / Separation of Test and Production Sites用于网站的 Git / 接收后 / 测试和生产站点的分离
【发布时间】:2010-02-02 18:02:46
【问题描述】:

我正在使用 Git 来管理我网站的源代码和部署,并且目前在同一个机器上运行测试和实时站点。最初遵循此资源http://toroid.org/ams/git-website-howto,我想出了以下接收后挂钩脚本来区分推送到我的实时站点和推送到我的测试站点:

while read ref
do
  #echo "Ref updated:"
  #echo $ref -- would print something like example at top of file
  result=`echo $ref | gawk -F' ' '{ print $3 }'`
  if [ $result != "" ]; then
    echo "Branch found: "
    echo $result
    case $result in
      refs/heads/master )
        git --work-tree=c:/temp/BLAH checkout -f master
        echo "Updated master"
        ;;
      refs/heads/testbranch )
        git --work-tree=c:/temp/BLAH2 checkout -f testbranch
        echo "Updated testbranch"
        ;;
      * )
        echo "No update known for $result"
        ;;
    esac
  fi
done
echo "Post-receive updates complete"

但是,我怀疑这实际上是否安全 :) 我绝不是 Git 专家,但我猜测 Git 可能会跟踪当前签出的分支头,这种方法可能具有潜力把它弄糊涂了。

所以有几个问题:

  1. 这样安全吗?

  2. 更好的方法是让我的基础存储库成为测试站点存储库(具有相应的工作目录),然后让该存储库将更改推送到新的实时站点存储库,该存储库具有对应的工作目录现场基地?这也将允许我将生产移动到不同的服务器并保持部署链完整。

  3. 我有什么遗漏吗?使用 Git 管理网站时,是否有一种不同的、简洁的方式来区分测试部署和生产部署?

根据 Vi 的回答,作为补充说明,有没有一种很好的方法可以处理删除而不会对文件系统造成太多影响?

谢谢, -沃尔特

PS - 我为多个 repos 提出的脚本(除非我听得更好,否则我正在使用)如下:

sitename=`basename \`pwd\``

while read ref
do
  #echo "Ref updated:"
  #echo $ref -- would print something like example at top of file
  result=`echo $ref | gawk -F' ' '{ print $3 }'`
  if [ $result != "" ]; then
    echo "Branch found: "
    echo $result
    case $result in
      refs/heads/master )
        git checkout -q -f master
        if [ $? -eq 0 ]; then
            echo "Test Site checked out properly"
        else
            echo "Failed to checkout test site!"
        fi
        ;;
      refs/heads/live-site )
        git push -q ../Live/$sitename live-site:master
        if [ $? -eq 0 ]; then
            echo "Live Site received updates properly"
        else
            echo "Failed to push updates to Live Site"
        fi
        ;;
      * )
        echo "No update known for $result"
        ;;
    esac
  fi
done
echo "Post-receive updates complete"

然后 ../Live/$sitename 中的存储库(这些是在 init 之后添加工作树的“裸”存储库)具有基本的 post-receive:

git checkout -f
if [ $? -eq 0 ]; then
    echo "Live site `basename \`pwd\`` checked out successfully"
else
    echo "Live site failed to checkout"
fi

【问题讨论】:

  • 目前我使用#2,到目前为止它看起来很干净,只要我记得在推送到实时站点后切换回测试存储库中的主分支。跨度>

标签: git web git-post-receive website-deployment


【解决方案1】:

认为这两种方法都行。

您也可以使用“git archive master | tar -C c:/temp/BLAH -x”和“git archive live-site | ssh live-site 'tar -C /var/www -x'”。

保持单独的存储库可能很有用,但“推入另一个与推相关的钩子”看起来很棘手,我预计它会很慢。有点长的链条,既慢又脆弱。

是否应该在测试“测试”版本后手动触发实时站点更新?

【讨论】:

  • 焦油可能是个好主意;下周我一定会看看这个。我不完全确定它的工作情况如何,因为我正在通过 msysGit 运行脚本。但是,它们似乎是用 tar 包装的,所以也许吧。
  • 好的 - 这是一个关于这个答案的问题 - 我喜欢 tarring 的概念,但有一个不令人满意的部分 - 我希望更新尽可能无缝。多个 repo 技巧的好处之一是,虽然很棘手,但文件系统仅根据每个提交的 deltas 进行更改 - 然而, tar 方法需要 rm -rf'ing 部署目录,然后提取 tar 。 . .也许有一个我不知道的焦油标志?由于多种原因,tar 方法很好,但我认为我的主机在更新之间删除所有内容是危险的。
  • 那么您可能应该使用单独的存储库。但我仍然不认为推送到一些特殊的参考应该自动更新生产站点。它不应该那么容易。
  • 使用“git checkout”更新站点本身并不是原子操作。某些用户在“结帐”时访问该站点会发生什么?您可以将站点提取/签出到其他目录并指向站点的配置文件以使用该其他目录。
  • 存储库中存储了哪些文件?像一些相互关联的小 PHP 文件或独立的大 blob?
【解决方案2】:

更好的方法是让我的 基础存储库是测试站点 存储库(具有相应的工作 目录),然后有 存储库将更改推送到新的实时 站点存储库,其中有一个 对应的工作目录 现场基地?这也将允许 我将生产转移到 不同的服务器并保持 部署链完好无损。

是的,当然。这是一个非常罕见的情况,您希望您的测试站点托管在您的生产站点旁边。这几乎在所有方面都是危险和不专业的,更不用说数据库损坏、网络服务器锁定等了。

我通常有一个用于测试目的的 VM 设置。效果很好,我可以在旅行时将它放在我的笔记本电脑上。

使用 git 来部署您的网站是一个非常好的主意,还有很多其他人在这样做(例如 Rob Conery)。如果您碰巧有一个实时和测试站点,您应该在您的存储库中为它们设置单独的分支,在相应的服务器存储库上设置为远程跟踪分支。您的工作流程变得像在测试分支中工作一样简单,将其推送到测试、测试、合并到实时和推送。

老实说,不要让自己太难。

【讨论】:

  • 这听起来像是要走的路/上周效果很好。
【解决方案3】:

我也在 toroid.org 上遵循了相同的指南,但我想指出,尽管您从一个裸存储库开始,但通过添加一个工作目录,很可能需要额外的处理。我发现如果您的内容可能会动态或以其他方式发生变化并且不想在使用git checkout -f时丢失数据,那么下面的钩子很有用@

预收

#!/bin/sh
git add -A
git diff --quiet --cached
if [ $? -gt 0 ]; then
    git commit --quiet -m "autocommit"
    echo "Working Directory was out of sync. Pull to receive updated index."
    exit 1
fi

如果远程工作目录发生更改,这将停止推送。将其视为某人(Web 服务器)进行更改但忘记提交它们。将checkout-f 一起使用将丢弃这些更改。这个钩子是防止这种情况发生的好地方,但如果在拉取之前在远程服务器上也调用一个钩子会很好,这样您就可以无缝地接收这些更改。

收到后

#!/bin/sh
git checkout -f
echo "Working directory synced."

关于有两个分支,我认为您的第一个解决方案比处理多个存储库更优雅。如果你真的想让你的生产站点保持隔离,你可以在本地使用 rsync ,它具有类似的增量补丁。我将在存储库中有一个测试和稳定的分支,只有测试站点作为工作目录。当准备好发布时,将测试合并到稳定分支,推送,并有一个钩子来寻找稳定分支的提交,然后调用 rsync。

【讨论】:

  • +1 用于预接收评论 - 这是一个非常有用的提示,谢谢。就多个存储库而言,实际上并不算太糟糕:) rsync 绝对是另一个可行的选择。谢谢!
  • git add . 没有收到所有更改(删除),改为git add -A
猜你喜欢
  • 2011-03-27
  • 2017-11-12
  • 1970-01-01
  • 1970-01-01
  • 2013-01-07
  • 2017-01-08
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
相关资源
最近更新 更多