Git Push错误:拒绝更新签出的分支


195

我已经解决了一些合并冲突,已提交然后尝试推送更改,并收到以下错误:

c:\Program Files (x86)\Git\bin\git.exe push --recurse-submodules=check "origin" master:master
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:/Development/GIT_Repo/Project
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'C:/Development/GIT_Repo/Project'

有谁知道是什么原因导致此错误?



6
您现在实际上已经有了使用Git 2.3.0(2015年2月)和git config receive.denyCurrentBranch=updateInsteadstackoverflow.com/a/28262104/6309
VonC

Answers:


228

原因:您正在推向非裸存储库

存储库有两种类型:裸机和非裸机

裸存储库没有工作副本,您可以推送到它们。这些就是您在Github中获得的存储库类型!如果要创建裸仓库,则可以使用

git init --bare

简而言之,您不能推送到非裸仓库(编辑:好吧,您不能推送到存储库的当前签出分支。使用裸存储库,由于没有签出,您可以推送到任何分支。尽管有可能,推送到非裸露的存储库并不常见) 。您可以做的是从另一个存储库获取并合并。这就是pull request您在Github中看到的方式。您要求他们从您身边拉开,并且不要强行推入他们。


更新:感谢VonC指出这一点,在最新的git版本(当前为2.3.0)中,可以推送到非裸仓库的已签出分支。但是,您仍然无法推入肮脏的工作树,无论如何这都不是安全的操作。


1
是! 这是正确的,谢谢!当我有大约一百万个工作要做时,我不小心克隆了工作目录.... doh!
时髦的

25
实际上,您可以很好地推送到非裸仓库,而不能推送到当前已签出的一个分支。
无处可见的人

1
实际上,还有许多其他方案。例如,我的某些存储库仅位于我的工作站和笔记本电脑上(不是代码,但要注意)。在每一个上我都有两个分支,“工作站”和“笔记本电脑”。在工作站上,我仅签出“工作站”,并且仅推送至笔记本电脑上的“工作站”分支(反之亦然)。

8
您现在实际上已经有了一种安全的方法,可以使用Git 2.3.0(2015年2月)和git config receive.denyCurrentBranch=updateInsteadstackoverflow.com/a/28262104/6309
VonC

1
@skelly您的克隆不是裸露的,而副本在github上。因此,尽管两个克隆都具有全部历史记录,但github上的副本没有任何提交检出,但是您的副本却可以执行任何工作!
Shahbaz

115

我首先通过验证该遥控器没有检出任何东西(实际上不应该这样做)来解决此问题,然后使用以下方法使其裸露:

$ git config --bool core.bare true

之后,git push正常运行。


3
这是我一直在寻找的一线解决方案。但是也许可以解释像@shahbaz答案这样的裸机回购
Mr5o1

这将允许推送更改历史记录,但是那些更改不会反映在非裸仓库中。
jhill515

你会git config core.bare falsegit reset --hard 吗?
飞机

1
如上所述,按下遥控器后,遥控器将不会被修改。
user1097111

46

摘要

您不能将其推送到存储库的一个已签出分支,因为它会以某种可能会以丢失数据和历史记录结束的方式使该存储库的用户混乱。但是您可以推送到同一存储库的任何其他分支。

由于裸存储库永远不会签出任何分支,因此您始终可以推送到裸存储库的任何分支。

验尸

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

所以

A ← B
    ↑
[HEAD,branch1]

变成

A ← B ← C
        ↑
    [HEAD,branch1]

但是,如果有人可以推到两者之间的那个分支,那么用户将自己陷入git所说的 分离头模式:

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

现在,该用户不再位于branch1中,而无需明确要求签出另一个分支。更糟糕的是,用户现在在任何分支机构之外,并且任何新提交都将悬而未决

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

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



21

cd进入要在远程计算机上推入的repo /目录,然后输入

$ git config core.bare true

这是行不通的。推送到存储库后,它保持为空。
索伦

正如上面的jhil515所说,非裸文件不会更新,只会更新数据库。
Denis Cousineau

19

对我而言,以下技巧可以解决:

git config --global receive.denyCurrentBranch updateInstead

我设置了驱动器F:,几乎完全使用Git在Windows 10台式机和Windows 10笔记本电脑之间进行同步。我最终在两台计算机上都运行了上面的命令。

首先,我在网络上共享了台式机的F驱动器。然后,我可以通过运行以下命令在笔记本电脑上克隆它:

F: git clone 'file://///DESKTOP-PC/f'

不幸的是,所有文件最终都放在笔记本电脑的“ F:\ f \”下,而不是直接在F:\下。但是我能够手动剪切和粘贴它们。之后,Git仍从新位置工作。

然后,我尝试对便携式计算机上的文件进行一些更改,将其提交,然后将其推回桌面。直到我运行了上面提到的git config命令,这才起作用。

请注意,我在两台计算机上都从Windows PowerShell内部运行了所有这些命令。

更新:在某些情况下,我在推动更改方面仍然遇到问题。我最终只是开始拉取更改,方法是在要将最新提交提交到的计算机上运行以下命令:

git pull --all --prune


1
我更喜欢git repo:git config receive.denyCurrentBranch updateInstead
klor

14

由于已经有一个现有的存储库,正在运行

git config --bool core.bare true

在远程存储库上就足够了

来自core.bare文档

如果为true(bare = true),则假定存储库为裸露,没有任何工作目录关联。如果是这种情况,那么将禁用许多需要工作目录的命令,例如git-add或git-merge(但您可以将其推送到其中)。

创建存储库时,git-clone或git-init会自动猜测此设置。默认情况下,以“ /.git”结尾的存储库被假定为不裸(bare = false),而所有其他存储库都被假定为裸(bare = true)。


12

TLDR

  1. 再次拉并推: git pull &&& git push
  2. 还有问题吗?推入不同的分支:git push origin master:foo并将其合并到远程仓库中。
  3. 或者,通过添加来强制执行推送-fdenyCurrentBranch需要忽略)。

基本上,该错误意味着您的存储库不是最新的远程代码(其索引和工作树与您推送的内容不一致)。

通常,您应该pull首先获取最近的更改,然后push然后再次获取。

如果没有帮助,请尝试推送到其他分支,例如:

git push origin master:foo

然后将远程存储库上的此分支与master合并。

如果您故意通过更改了一些过去的提交,git rebase并且您想用所做的更改覆盖回购,则可能要通过添加-f/ --force参数来强制执行推送(如果不这样做,则不推荐rebase)。如果仍然无法使用,您需要通过以下方式根据git消息的建议设置receive.denyCurrentBranchignoreremote:

git config receive.denyCurrentBranch ignore

3

也许您的远程仓库位于您要推送的分支中。您可以尝试签出远程计算机中的另一个分支。我这样做了,然后这些错误消失了,我将成功推到了我的远程仓库中。请注意,我使用ssh而不是github.com来连接我自己的服务器。


1

我有这个错误,因为git repo被(偶然地)在同一位置初始化了两次:首先是一个非裸仓库,不久之后是裸仓库。由于.git文件夹仍然存在,因此git假定存储库是非裸露的。删除.git文件夹和工作目录数据可以解决此问题。


1
以我的情况,就是这种情况。删除.git遥控器上的文件夹后,我就可以推送初始提交了。
tim.rohrer

0

我在阅读progit时在玩耍时遇到此错误。我创建了一个本地存储库,然后在同一文件系统上的另一个存储库中将其获取,进行了编辑并尝试推送。阅读NowhereMan的答案后,一个快速的解决方法是转到“远程”目录并临时签出另一个提交,从我进行更改的目录中推送,然后返回并重新放置在master上。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.