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

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

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'

有人知道是什么导致了这个错误吗?

229421 次浏览

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

有两种类型的存储库:裸露与非裸露

裸存储库没有工作副本,您可以将其推入。这些就是你在Github中得到的存储库类型!如果您想创建一个裸存储库,可以使用

git init --bare

因此,简而言之,不能推送到非裸存储库(编辑:嗯,你不能推到存储库的当前签出的分支。使用裸存储库,您可以推送到任何分支,因为没有任何分支被签出。尽管可能,但推入非裸存储库并不常见)。你能做的就是从其他存储库中获取并合并。这就是你在Github中看到的pull request的工作方式。你让他们离开你,而不是强迫他们。


更新:感谢VonC指出这一点,在最新的git版本(目前是2.3.0)中,推入非裸存储库的检出分支是可能的. 更新。然而,你仍然不能推入工作树,这不是一个安全的操作。

总结

你不能推到一个储存库的检出分支,因为它会扰乱储存库的用户,很可能以丢失数据和历史记录结束。但是您可以推送到同一存储库的任何其他分支。

由于裸存储库从来没有检出过任何分支,所以您总是可以推入裸存储库的任何分支。

问题的解剖

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

所以

A ← B
↑
[HEAD,branch1]

就变成了

A ← B ← C
↑
[HEAD,branch1]

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

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

现在用户不再在branch1中,没有显式地要求签出另一个分支。更糟糕的是,用户现在是在任何分支机构外,任何新的提交都将是晃来晃去的:

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

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

也许您的远程回购在您想要推送的分支中。您可以尝试在远程机器上签出另一个分支。我这样做了,这些错误消失了,我把成功推到我的远程回购。注意,我使用ssh连接我自己的服务器,而不是github.com。

我解决了这个问题,首先验证该遥控器没有任何检出(它真的不应该),然后使它裸露:

$ git config --bool core.bare true

在那之后,git推得很好。

TLDR

  1. 拉,再次push: git pull &&& git push
  2. 还是个问题吗?推入不同的分支:git push origin master:foo并在远程回购中合并它。
  3. 或者通过添加-f强制推(denyCurrentBranch需要被忽略)。

基本上,这个错误意味着您的存储库与远程代码没有更新(它的索引和工作树与您推送的内容不一致)。

通常你应该先pull来获取最近的更改,然后再push它。

如果没有帮助,尝试推到不同的分支,例如:

git push origin master:foo

然后将远程存储库上的这个分支合并回master。

如果你故意通过git rebase改变了一些过去的提交,并且你想用你的更改覆盖repo,你可能想通过添加-f/--force参数来强制推送(如果你没有做rebase,不推荐)。如果仍然无效,你需要在远程上将receive.denyCurrentBranch设置为ignore,就像git消息所建议的那样:

git config receive.denyCurrentBranch ignore

因为已经有一个现有的存储库正在运行

git config --bool core.bare true

在远程存储库上就足够了

从核心开始。裸露的文档

如果为true (bare = true),则假定存储库是空的,没有关联的工作目录。如果是这种情况,许多需要工作目录的命令将被禁用,例如git-add或git-merge(但您将能够推到它)。

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

CD到您在远程计算机上插入的repo/目录中,然后输入

$ git config core.bare true

对我来说,以下几点很管用:

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

我有这个错误,因为git回购(意外地)初始化两次在同一位置:第一次作为一个非裸回购和不久之后作为一个裸回购。因为.git文件夹仍然存在,所以git假定存储库是非裸的。删除.git文件夹和工作目录数据解决了这个问题。

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

这对我很有用

  1. < p > git config --global receive.denyCurrentBranch updateInstead

  2. < p > git push origin master

正如在其他答案中提到的,你不能推到检出的分支。让我们从这里开始。

从远程服务器,让我们将远程存储库签入到一个临时分支。

git checkout -b temp

现在,我们可以从本地存储库推送到主分支。

git push

但这不是长久之计。未来的推动将带来同样的问题。为了一劳永逸地解决这个问题,您需要将远程存储库转换为裸存储库。从远程服务器输入:

git config core.bare true

现在你可以毫无问题地推到遥控器了。

以后,使用--bare选项创建远程存储库,如下所示:

git init --bare

我也有同样的问题,我试着这样做:

  1. Ssh到gitlab服务器(远程服务器机器而不是你的个人机器),发现[core]:bare value is false in yourRepo/.git/config

enter image description here

< p > 2。Vim配置并将其编辑为true 现在,它很好。

在另一个帖子的答案解释这个问题。 在我看来,更好的方法是:

  1. 对于远程服务器中的存储库:git branch -b workwork是一个专门用于远程服务器的工作分支。
  2. 将本地提交推到远程服务器,本地分支的名称(dev)应该与work不同,以避免混乱,现在git push origin dev将不会出现错误。
  3. 在远程服务器中合并devworkgit merge