使用git + post-receive hook管理网站:推送更改时出错

时间:2012-06-05 18:10:34

标签: git web push

问题:如果该工作树不是裸机,如何将我的本地提交推送到我的开发服务器?

我的情况:

  1. 我在我的开发服务器上设置了git,这样当我推送本地更改时,它们会被添加到一个独立的工作树(described here,就像this post一样)。
  2. 然后我在开发服务器上运行git时遇到了问题(例如,git status),因为git找不到工作树。
  3. 我问过SO和got the tip off我需要在配置文件中设置bare = false并指定工作树。甜。
  4. 但是现在当我尝试将我的提交推送到开发服务器时,我收到了这个错误:

    $ git push origin master
    xxxx@xxx.xxx.xxx.xxx's password:
    Counting objects: 26, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (18/18), done.
    Writing objects: 100% (18/18), 2.56 KiB, done.
    Total 18 (delta 8), reused 0 (delta 0)
    
    remote: error: refusing to update checked out branch: refs/heads/master
    remote: error: By default, updating the current branch in a non-bare repository
    remote: error: is denied, because it will make the index and work tree inconsistent
    remote: error: with what you pushed, and will require 'git reset --hard' to match
    remote: error: the work tree to HEAD.
    remote: error:
    remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
    remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
    remote: error: its current branch; however, this is not recommended unless you
    remote: error: arranged to update its work tree to match what you pushed in some
    remote: error: other way.
    remote: error:
    remote: error: To squelch this message and still keep the default behaviour, set
    remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
    
    To ssh://xxxx@xxx.xxx.xxx.xxx/xxx/xxx/xxxxxx.git
     ! [remote rejected] master -> master (branch is currently checked out)
    error: failed to push some refs to 'ssh://xxxx@xxx.xxx.xxx.xxx/xxx/xxx/xxxxxx.git'
    

    我看到this other user had the same problem。不幸的是,对他有用的解决方案是在他的配置中设置bare = true,这将重现我在上面的步骤3中遇到的问题。

    错误消息显示

      

    您可以将'receive.denyCurrentBranch'配置变量设置为   remote:错误:'忽略'或'警告'

    在我的情况下,我可以这样做吗?这对我来说听起来不错,但是我对git还不够熟悉,但是当它出现时我还没认识到一个坏主意......

    修改

    为了清楚起见,我已经添加了一个post-receive hook,它运行顺畅。问题是我似乎必须在bare=true(能够推送到开发服务器)和bare=false之间进行选择(并且能够在开发服务器上运行git命令)。

4 个答案:

答案 0 :(得分:2)

为什么不:

  • 将您的提交推送到一个裸仓库
  • 在该dev repo上设置一个post-receive hook,然后转到非裸dev repo并检查右边的分支,从裸仓库中提取新的提交?

这就是your link描述的内容(使用分离的工作树),但它在一个简单的仓库中设置了钩子:

$ mkdir /var/www/www.example.org
$ cat > hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/var/www/www.example.org git checkout -f
$ chmod +x hooks/post-receive

答案 1 :(得分:0)

使用存储库不是您想要做的。您需要在开发服务器上的裸存储库中使用post-receive挂钩,该存储库对您的Web服务器目录执行git checkout-index。这样,它只是文件。你不必担心它是一个裸存储库,有一个工作树,还是其他任何与git相关的东西。

git checkout-index -f -a --prefix=/var/www/htdocs/mywebsite/之类的东西(注意尾随斜线 - 这很重要)

-f标志将强制覆盖任何现有文件,-a标志将包含所有文件。

答案 2 :(得分:0)

你只需要小心你要做的事情。

git status用于告诉您工作树的状态。这在你的情况下应该没用。

另一方面,git push在裸存储库上完全有效。这应该适合你。

如果您想查看更改,可以使用git diff。您只需指定两个哈希git diff $oldref $newref

如果要列出特定提交中更改的文件,请使用git show --pretty="format:" --name-only $newref

如果要列出文件的内容,请使用git show $newref -- $filepath

答案 3 :(得分:0)

我已经找到了一个可以接受但不太理想的解决方案。基本上,当我需要将dev更改推送到我的实时服务器时,我只是通过编辑配置文件来避免这个问题。

Config文件,允许开发人员将本地更改推送到dev:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = true

将dev更改为live时配置文件:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        worktree = /var/www/example.com/httpd/

<强>赞成

  1. 作品
  2. 一旦我将配置文件更改为push to live,repo就会被“锁定”而其他开发人员无法推送更改
  3. 不是一个大问题,因为我必须登录dev来处理数据库迁移
  4. 缺点:如果我知道如何正确地做到这一点,基本上就是我确信它可以实现自动化。

    注意:我喜欢@ vonC建议设置post-receive hook以有条件地推送到实时服务器。对post-receive钩子进行更改很简单,但是我不明白钩子会响应什么触发器。我很乐意听到建议:)