【问题标题】:Git post-receive hook doesn't remove deleted files from masterGit post-receive hook不会从master中删除已删除的文件
【发布时间】:2013-09-29 09:37:05
【问题描述】:

我在我的服务器上创建了一个裸 git repo,并从this blog 设置了以下接收后挂钩:

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

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

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

【问题讨论】:

    标签: git git-post-receive


    【解决方案1】:

    我遇到了同样的问题。正在研究 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
    

    【讨论】:

      【解决方案2】:

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

      注意:如果存在名为 master 或 develop 的标签,因为这两个标签的引用名称分别为 refs/tags/master 和 refs/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
      

      (注意:完全未经测试)。

      【讨论】:

      • 如果存储库是裸存储库,git-work-tree 会按预期工作吗??
      • 是的,或者至少,它确实适用于 env 变量,它也应该适用于命令行选项。
      • 我收到一个错误:remote: mv: cannot move '/path/to/my/project/dev/' to a subdirectory of its own, '/path/to/my/project/dev/ .old.847' 和远程:无法将实时版本移开
      • 看起来你在“部署”的参数中留下了一个斜杠。它要求您不在其中包含它们(它会根据需要自行添加)。
      • 现在它似乎工作了。谢谢!如果项目变得更大,我应该担心那个窗口吗?
      猜你喜欢
      • 2018-02-02
      • 2012-07-09
      • 2013-04-29
      • 2015-03-22
      • 1970-01-01
      • 1970-01-01
      • 2013-06-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多