在 Git 中使用 receive.denyCurrentBranch 有什么后果?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12265729/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 14:31:57  来源:igfitidea点击:

What are the consequences of using receive.denyCurrentBranch in Git?

gitgit-pushgit-configgit-non-bare-repository

提问by user1646481

I have a Git repository. I have cloned the repository and can commit my local changes. When I push my changes to the server it works.

我有一个 Git 存储库。我已经克隆了存储库并且可以提交我的本地更改。当我将更改推送到服务器时,它可以工作。

As soon as I create a branch, I checkout the branch, commit my work and then checkout the master branch. I then merge my local changes into the master branch. When I try to push to the server I get the following exception:

一旦我创建了一个分支,我就会检出分支,提交我的工作,然后检出主分支。然后我将我的本地更改合并到主分支中。当我尝试推送到服务器时,出现以下异常:

Welcome to Git (version 1.7.11-preview20120620)

Run 'git help git' to display the help index.
Run 'git help <command>' to display help for specific commands.

$ git push origin master:master
 Counting objects: 9, done.
 Delta compression using up to 4 threads.
 Compressing objects: 100% (7/7), done.
 Writing objects: 100% (8/8), 13.68 KiB, done.
 Total 8 (delta 2), reused 1 (delta 0)
 Unpacking objects: 100% (8/8), done.
 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 c:/jGit
 ! [remote rejected] master -> master (branch is currently checked out)
 error: failed to push some refs to 'c:/gitRepository'

One solution is to run the following command:

一种解决方案是运行以​​下命令:

git config receive.denyCurrentBranch ignore

After this it works, but I would like to know why I need to use this option. Is this the only option? What are the consequences of doing this?

在此之后它可以工作,但我想知道为什么我需要使用这个选项。这是唯一的选择吗?这样做的后果是什么?

What I would really like to do is create branches, merge them into the master branch and then push my changes to the server.

我真正想做的是创建分支,将它们合并到 master 分支,然后将我的更改推送到服务器。

采纳答案by kan

The server where you are pushing to should use bare repository.

您推送到的服务器应该使用裸存储库。

How to convert a normal Git repository to a bare one?

如何将普通的 Git 存储库转换为裸存储库?

回答by kan

Why Git won't let you push to non-bare repositories

为什么 Git 不允许你推送到非裸仓库

The original poster says:

原海报说:

One solution is to run the following command:

git config receive.denyCurrentBranch ignore

After this it works, but I would like to know why I need to use this option. Is this the only option? What are the consequences of doing this?

一种解决方案是运行以​​下命令:

git config receive.denyCurrentBranch ignore

在此之后它可以工作,但我想知道为什么我需要使用这个选项。这是唯一的选择吗?这样做的后果是什么?

As I point out in my answer to a similar question, since Git version 1.6.2, Git won't let you push to a non-bare repository by default. This is because the git pushcommand only updates the branch and HEADreferences on the remote repository. What it doesn'tdo is also update the working-copy and staging-area in that non-bare remote.

正如我在对类似问题的回答中指出的那样,自 Git 版本 1.6.2 起,Git 默认不会让您推送到非裸存储库。这是因为该git push命令仅更新HEAD远程存储库上的分支和引用。它所就也是在非裸远程更新工作拷贝和舞台区。

As a consequence, when you use git statusin the remote repo, you'll see that the repo's previous state is still present in the working copy (and staged in the index):

因此,当您git status在远程存储库中使用时,您会看到该存储库的先前状态仍然存在于工作副本中(并在索引中暂存):

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   previous-state.txt

If you look at the error message that you got when you first tried to push to your non-bare remote repo with the receive.denyCurrentBranchsetting set to the default refusevalue, you'll see that the message tells you basically the same thing:

如果您查看第一次尝试推送到您的非裸远程存储库并将receive.denyCurrentBranch设置设置为默认refuse值时收到的错误消息,您会看到该消息告诉您基本相同的事情:

error: refusing to update checked out branch: refs/heads/master
error: By default, updating the current branch in a non-bare repository
error: is denied, because it will make the index and work tree inconsistent
error: with what you pushed, and will require 'git reset --hard' to match
error: the work tree to HEAD.
error:
error: You can set 'receive.denyCurrentBranch' configuration variable to
error: 'ignore' or 'warn' in the remote repository to allow pushing into
error: its current branch; however, this is not recommended unless you
error: arranged to update its work tree to match what you pushed in some
error: other way.

You should really just push to bare Git repositories

你真的应该推送到裸 Git 存储库

As pointed out in some ofthe other answers, you shouldn't really be pushing to a non-bare repository, for the reasons I pointed out above, and which Git itself is telling you.

正如指出的一些其他的答案,你真不该推到非纯仓库,因为我上面所指出的原因,和Git的本身告诉你的。

So like what this answerstates, a simple way to convert an existing non-bare repo to a bare one is to simply reclone it as a bare repo:

因此,就像这个答案所说的那样,将现有的非裸存储库转换为裸存储库的一种简单方法是简单地将其重新克隆为裸存储库:

git clone --bare old-repo

Or you could try messing around with the core.bareconfig setting, as detailed in this answer.

或者您可以尝试修改core.bare配置设置,如本答案中所述

回答by Fanky

I had the same error and needed the repository to be running as a dev test page online (that is, I guess, to keep a non-bare repo). Hopefully I solved it by initiating the repository with this series of commands (since git 2.3):

我遇到了同样的错误,需要存储库作为在线开发测试页面运行(也就是说,我想,要保留一个非裸存储库)。希望我通过使用这一系列命令(从 gi​​t 2.3 开始)启动存储库来解决它:

git init
git config --global user.email "[email protected]"
git config --global user.name "Your Name"
git commit
git config receive.denyCurrentBranch updateInstead

As seen here: cannot push into git repository

如此处所示: 无法推送到 git 存储库

回答by Carl-Eric Menzel

You should have a bare repository on the server, not one with a checked-out working tree. Git is telling you it refuses to overwrite the branch that is currently checked out on the server.

您应该在服务器上有一个裸存储库,而不是带有检出工作树的存储库。Git 告诉你它拒绝覆盖当前在服务器上检出的分支。

See this answerfor information on how to convert your non-bare repository on the server to a bare one.

有关如何将服务器上的非裸存储库转换为裸存储库的信息,请参阅此答案

回答by Harshal Doshi Jain

Autopsy of the Problem

问题的尸检

When a branch is checked out, committing will add a new commit with the current branch's head as its parent and move the branch's head to be that new commit.

当一个分支被检出时,提交将添加一个以当前分支的头作为其父级的新提交,并将该分支的头移动到该新提交。

So

所以

A ← B
    ↑
[HEAD,branch1]

becomes

变成

A ← B ← C
        ↑
    [HEAD,branch1]

But if someone could push to that branch inbetween, the user would get itself in what git calls detached head mode:

但是如果有人可以推送到中间的那个分支,用户就会进入 git 所说的分离头模式:

A ← B ← X
    ↑   ↑
[HEAD] [branch1]

Now the user is not in branch1 anymore, without having explicitly asked to check out another branch. Worse, the user is now outside any branch, and any new commit will just be dangling:

现在用户不再在 branch1 中,而没有明确要求签出另一个分支。更糟糕的是,用户现在在任何分支之外,任何新的提交都将悬而未决:

     [HEAD]
        ↓
        C
      ↙
A ← B ← X
        ↑
       [branch1]

Hypothetically, if at this point, the user checks out another branch, then this dangling commit becomes fair game for Git's garbage collector.

假设,如果此时用户签出另一个分支,那么这个悬空提交对于 Git 的垃圾收集器来说就变成了公平的游戏。

回答by kisp

I think a non bare repository can be useful when man configures the git update hookto deploy from the repository itself after the push happened. Just do not forget to reset the repository. If you miss that step files wont track the actual state...

我认为当 man 配置 git update 挂钩以在推送发生后从存储库本身进行部署时,非裸存储库会很有用。只是不要忘记重置存储库。如果您错过了该步骤文件将不会跟踪实际状态...