Git 推送错误“[远程拒绝] master -> master(分支当前已检出)”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2816369/
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 08:22:40  来源:igfitidea点击:

Git push error '[remote rejected] master -> master (branch is currently checked out)'

gitgit-push

提问by hap497

Yesterday, I posted a question on how to clone a Gitrepository from one of my machines to another, How can I 'git clone' from another machine?.

昨天,我发布了一个关于如何将Git存储库从我的一台机器克隆到另一台机器的问题,我如何从另一台机器“git clone”?.

I am now able to successfully clone a Git repository from my source (192.168.1.2) to my destination (192.168.1.1).

我现在可以成功地将 Git 存储库从我的源 (192.168.1.2) 克隆到我的目标 (192.168.1.1)。

But when I did an edit to a file, a git commit -a -m "test"and a git push, I get this error on my destination (192.168.1.1):

但是,当我对文件 agit commit -a -m "test"和 a进行编辑时git push,我在目的地 (192.168.1.1) 上收到此错误:

git push                                                
[email protected]'s password: 
Counting objects: 21, done.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (11/11), 1010 bytes, done.
Total 11 (delta 9), reused 0 (delta 0)
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.
error: 
error: To squelch this message and still keep the default behaviour, set
error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To git+ssh://[email protected]/media/LINUXDATA/working
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'git+ssh://[email protected]/media/LINUXDATA/working'

I'm using two different versions of Git (1.7 on the remote and 1.5 on the local machine). Is that a possible reason?

我正在使用两个不同版本的 Git(远程 1.7 和本地机器 1.5)。这是一个可能的原因吗?

回答by John

You can simply convert your remote repository to bare repository (there is no working copy in the bare repository - the folder contains only the actual repository data).

您可以简单地将远程存储库转换为裸存储库(裸存储库中没有工作副本 - 该文件夹仅包含实际存储库数据)。

Execute the following command in your remote repository folder:

在远程存储库文件夹中执行以下命令:

git config --bool core.bare true

Then delete all the files except .gitin that folder. And then you will be able to perform git pushto the remote repository without any errors.

然后删除除.git该文件夹中的所有文件。然后您将能够在git push没有任何错误的情况下执行到远程存储库。

回答by Robert Gould

I just had the same error while I began learning Git. Some of the other answers are clearly not for someone new to Git!

我刚开始学习Git时遇到了同样的错误。其他一些答案显然不适合 Git 新手!

(I am going to use non technical terms to get the idea across.) Anyway, what is happening is that you have two repositories, one is the original you first made, and the other the work one you just made.

(我将使用非技术术语来表达这个想法。)无论如何,发生的事情是你有两个存储库,一个是你第一次制作的原件,另一个是你刚刚制作的作品。

Right now you are in your work repository and are using the "master" branch. But you also happen to be "logged in" in your original repository to the same "master" branch. Now since you're "logged in" in the original, Git fears you might mess up because you might be working on the original and screw things up. So you need to return to the original repository and do a "git checkout someotherbranch", and now you can push with no problems.

现在您在您的工作存储库中并且正在使用“master”分支。但是您也碰巧在原始存储库中“登录”到同一个“主”分支。现在,由于您在原始版本中“登录”,Git 担心您可能会搞砸,因为您可能正在处理原始版本并将事情搞砸。因此,您需要返回原始存储库并执行“git checkout someotherbranch”,现在您可以毫无问题地进行推送。

I hope this helps.

我希望这有帮助。

回答by CB Bailey

The error message describes what has happened. More modern versions of Git refuse to update a branch via a push if that branch is checked out.

错误消息描述了发生了什么。如果分支被检出,更现代的 Git 版本拒绝通过推送更新分支。

The easiest way to work between two non-bare repositories is either to

在两个非裸存储库之间工作的最简单方法是

  1. always update the repositories by pull (or fetch and merge) or, if you have to,

  2. by pushing to a separate branch (an import branch) and then merging that branch into the master branch on the remote machine.

  1. 始终通过拉取(或获取和合并)来更新存储库,或者,如果必须,

  2. 通过推送到一个单独的分支(一个导入分支),然后将该分支合并到远程机器上的主分支中。

The reason for this restriction is that the push operation operates only on the remote Git repository, it doesn't have access to the index and working tree. So, if allowed, a push on the checked-out branch would change theHEADto be inconsistent with the index and working tree on the remote repository.

这个限制的原因是推送操作只在远程 Git 存储库上操作,它无法访问索引和工作树。因此,如果允许,对签出分支的推送将更改为HEAD与远程存储库上的索引和工作树不一致。

This would make it very easy to accidentally commit a change that undoes all of the pushed changesand also makes it very difficult to distinguish between any local changes that have not been committed and differences between the new HEAD, the index and the working tree that have been caused by push moving HEAD.

这将很容易意外提交撤销所有推送的更改的更改,并且也很难区分尚未提交的任何本地更改以及已提交的新HEAD、索引和工作树之间的差异。推动所致HEAD

回答by Nowhere man

Summary

概括

You cannot push to the one checked out branch of a repository because it would mess with the user of that repository in a way that will most probably end with loss of data and history. But you can push to any other branch of the same repository.

您不能推送到存储库的一个检出分支,因为它会以一种很可能以丢失数据和历史记录而告终的方式干扰该存储库的用户。但是您可以推送到同一存储库的任何其他分支。

As bare repositories never have any branch checked out, you can always push to any branch of a bare repository.

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

There are multiple solutions, depending on your needs.

根据您的需要,有多种解决方案。

Solution 1: Use a Bare Repostiory

解决方案 1:使用裸存储库

As suggested, if on one machine, you don't need the working directory, you can move to a bare repository. To avoid messing with the repository, you can just clone it:

正如建议的那样,如果在一台机器上,您不需要工作目录,则可以移动到裸存储库。为了避免弄乱存储库,您可以克隆它:

machine1$ cd ..
machine1$ mv repo repo.old
machine1$ git clone --bare repo.old repo

Now you can push all you want to the same address as before.

现在您可以像以前一样将您想要的所有内容推送到相同的地址。

Solution 2: Push to a Non-Checked-Out Branch

解决方案 2:推送到未签出的分支

But if you need to check out the code on your remote <remote>, then you can use a special branch to push. Let's say that in your local repository you have called your remote originand you're on branch master. Then you could do

但是如果你需要检查遥控器上的代码<remote>,那么你可以使用一个特殊的分支来推送。假设您在本地存储库中调用了远程存储库,origin并且您在分支 master 上。那么你可以做

machine2$ git push origin master:master+machine2

Then you need to merge it when you're in the originremote repo:

然后你需要在origin远程仓库中合并它:

machine1$ git merge master+machine2

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 headmode:

但是如果有人可以推送到中间的那个分支,用户就会进入 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 Kris

You can get around this "limitation" by editing the .git/configon the destination server. Add the following to allow a git repository to be pushed to even if it is "checked out":

您可以通过编辑.git/config目标服务器上的来绕过此“限制” 。添加以下内容以允许将 git 存储库推送到,即使它已“签出”:

[receive]
denyCurrentBranch = warn

or

或者

[receive]
denyCurrentBranch = false

The first will allow the push while warning of the possibility to mess up the branch, whereas the second will just quietly allow it.

第一个将允许推送,同时警告可能弄乱分支的可能性,而第二个将只是悄悄地允许它。

This can be used to "deploy" code to a server which is not meant for editing. This is not the best approach, but a quick one for deploying code.

这可用于将代码“部署”到不用于编辑的服务器。这不是最好的方法,而是一种用于部署代码的快速方法。

回答by stackdump

I like the idea of still having a usable repository on the remote box, but instead of a dummy branch, I like to use:

我喜欢在远程机器上仍然有一个可用存储库的想法,但我喜欢使用:

git checkout --detach

This seems to be a very new feature of Git- I'm using git version 1.7.7.4.

这似乎是Git 的一个非常新的特性——我使用的是 1.7.7.4 版的 git。

回答by Orbital_sFear

I had the same issue. For me, I use Git push to move code to my servers. I never change the code on the server side, so this is safe.

我遇到过同样的问题。对我来说,我使用 Git push 将代码移动到我的服务器。我从不更改服务器端的代码,所以这是安全的。

In the repository, you are pushing to type:

在存储库中,您正在推动键入:

git config receive.denyCurrentBranch ignore

This will allow you to change the repository while it's a working copy.

这将允许您在它是工作副本时更改存储库。

After you run a Git push, go to the remote machine and type this:

运行 Git 推送后,转到远程机器并键入以下内容:

git checkout -f

This will make the changes you pushed be reflected in the working copy of the remote machine.

这将使您推送的更改反映在远程机器的工作副本中。

Please note, this isn't always safe if you make changes on in the working copy that you're pushing to.

请注意,如果您在推送到的工作副本中进行更改,这并不总是安全的。

回答by nau

You can recreate your server repository and push from your local branch master to the server master.

您可以重新创建服务器存储库并从本地分支 master 推送到服务器 master。

On your remote server:

在您的远程服务器上:

mkdir myrepo.git
cd myrepo.git
git init --bare

OK, from your local branch:

好的,来自您当地的分支机构:

git push origin master:master

回答by Jemenake

What you probably did to cause this:

你可能做了什么导致这种情况:

This kind of thing happens when you go to bang out a little program. You're about to change something which was already working, so you cast your level-3 spell of perpetual undoability:

这种事情发生在你去敲一个小程序的时候。你将要改变一些已经在起作用的东西,所以你施放了你的 3 级永久可撤销性咒语:

machine1:~/proj1> git init

and you start adding/committing. But then, the project starts getting more involved and you want to work on it from another computer (like your home PC or laptop), so you do something like

然后你开始添加/提交。但随后,该项目开始更多地参与,你想它的工作从另一台计算机(如您的家庭PC或笔记本电脑),所以你这样做

machine2:~> git clone ssh://machine1/~/proj1

and it clones and everything looks good, and so you work on your code from machine2.

它会克隆,一切看起来都不错,因此您可以从 machine2 处理代码。

Then... you try to push your commits from machine2, and you get the warning message in the title.

然后……您尝试从 machine2 推送您的提交,并在标题中收到警告消息。

The reason for this message is because the git repo you pulled from was kinda intended to be used just for that folder on machine1. You can clonefrom it just fine, but pushing can cause problems. The "proper" way to be managing the code in two different locations is with a "bare" repo, like has been suggested. A bare repo isn't designed to have any work being done init, it is meant to coordinate the commits from multiple sources. This is why the top-rated answer suggests deletingall files/folders other than the .git folder after you git config --bool core.bare true.

此消息的原因是因为您从中提取的 git 存储库旨在仅用于 machine1 上的该文件夹。您可以很好地从它克隆,但推送可能会导致问题。在两个不同位置管理代码的“正确”方法是使用“裸”存储库,就像已经建议的那样。裸回购没有设计有什么工作正在进行,它是为了协调来自多个来源的提交。这就是为什么评分最高的答案建议删除.git 文件夹以外的所有文件/文件夹git config --bool core.bare true

Clarifying the top-rated answer:Many of the comments to that answer say something like "I didn't delete the non-.git files from the machine1 and I was still able to commit from machine2". That's right. However, those other files are completely "divorced" from the git repo, now. Go try git statusin there and you should see something like "fatal: This operation must be run in a work tree". So, the suggestion to delete the files isn't so that the commit from machine2 will work; it's so that you don't get confused and think that git is still tracking those files. But, deleting the files is a problem if you still want to work on the files on machine1, isn't it?

澄清评分最高的答案:对该答案的许多评论都说“我没有从 machine1 中删除非 .git 文件,但我仍然能够从 machine2 提交”。这是正确的。但是,这些其他文件现在完全与 git 存储库“分离”了。去git status那里试试,你应该会看到类似“致命的:此操作必须在工作树中运行”之类的内容。因此,删除文件的建议并不是为了让 machine2 的提交起作用;这样您就不会感到困惑并认为 git 仍在跟踪这些文件。但是,如果您仍然想处理 machine1 上的文件,删除文件是个问题,不是吗?

So, what should you really do?

那么,你真的应该怎么做?

Depends upon how much you plan to still work on machine1 and machine2...

取决于您计划在 machine1 和 machine2 上继续工作的程度...

If you're done developing from machine1 and have moved all of your development to machine2...just do what the top-rated answer suggests: git config --bool core.bare trueand then, optionally, delete all files/folders other than .git from that folder, since they're untracked and likely to cause confusion.

如果您已完成从 machine1 的开发并将所有开发移至 machine2 ......只需按照最受好评的答案建议:git config --bool core.bare true然后,可选地,从该文件夹中删除 .git 以外的所有文件/文件夹,因为它们'未被跟踪,可能会引起混乱。

If your work on machine2 was just a one-time thing, and you don't need to continue development there...then don't bother with making a bare repo; just ftp/rsync/scp/etc. your files from machine*2* on top of the files on machine*1*, commit/push from machine*1*, and then delete the files off of machine*2*. Others have suggested creating a branch, but I think that's a little messy if you just want to merge some development you did on a one-time basis from another machine.

如果您在 machine2 上的工作只是一次性的,并且您不需要在那里继续开发……那么不要费心制作一个裸仓库;只是 ftp/rsync/scp/等。将机器*2* 上的文件放在机器*1* 上的文件之上,从机器*1* 提交/推送,然后从机器*2* 上删除文件。其他人建议创建一个分支,但我认为如果你只是想合并你在另一台机器上一次性完成的一些开发,那会有点混乱。

If you need to continue development on both machine1 and machine2...then you need to set things up properly. You need to convert your repo to a bare, thenyou need to make a clone of that on machine1 for you to workin. Probably the quickest way to do this is to do

如果您需要在 machine1 和 machine2 上继续开发......那么您需要正确设置。你需要将你的 repo 转换为一个裸的,然后你需要在 machine1 上制作一个克隆来让你工作。 可能最快的方法是这样做

machine1:~/proj1> git config --bool core.bare true
machine1:~/proj1> mv .git/ ../proj1.git
machine1:~/proj1> cd ..
machine1:~> rm -rf proj1
machine1:~> git clone proj1.git
machine1:~> cd proj1

Very important:because you've moved the location of the repo from proj1 to proj1.git, you need to update this in the .git/config file on machine2. After that, you can commit your changes from machine2. Lastly, I try to keep my bare repos in a central location, away from my work trees (i.e. don't put 'proj1.git' in the same parent folder as 'proj1'). I advise you to do likewise, but I wanted to keep the steps above as simple as possible.

非常重要:因为您已将 repo 的位置从 proj1 移动到 proj1.git,您需要在 machine2 上的 .git/config 文件中更新它。之后,您可以从 machine2 提交更改。最后,我尝试将我的裸仓库放在一个中心位置,远离我的工作树(即不要将“proj1.git”与“proj1”放在同一个父文件夹中)。我建议您也这样做,但我希望上述步骤尽可能简单。

回答by Hyman Senechal

With a few setup steps you can easily deploy changes to your website using a one-liner like

通过几个设置步骤,您可以使用单行程序轻松地将更改部署到您的网站

git push production

Which is nice and simple, and you don't have to log into the remote server and do a pull or anything. Note that this will work best if you don't use your production checkout as a working branch! (The OP was working within a slightly different context, and I think @Robert Gould's solution addressed it well. This solution is more appropriate for deployment to a remote server.)

这很好也很简单,您不必登录远程服务器并执行拉取或任何操作。请注意,如果您不将生产结帐用作工作分支,这将最有效!(OP 在稍微不同的上下文中工作,我认为 @Robert Gould 的解决方案很好地解决了这个问题。这个解决方案更适合部署到远程服务器。)

First you need to set up a bare repository somewhere on your server, outside of your webroot.

首先,您需要在服务器上的某个地方设置一个裸存储库,位于您的 webroot 之外。

mkdir mywebsite.git
cd mywebsite.git
git init --bare

Then create file hooks/post-receive:

然后创建文件hooks/post-receive

#!/bin/sh
GIT_WORK_TREE=/path/to/webroot/of/mywebsite git checkout -f

And make the file executable:

并使文件可执行:

chmod +x hooks/post-receive

On your local machine,

在您的本地机器上,

git remote add production [email protected]:mywebsite.git
git push production +master:refs/heads/master

All set! Now in the future you can use git push productionto deploy your changes!

搞定!现在将来您可以使用它git push production来部署您的更改!

Credit for this solution goes to http://sebduggan.com/blog/deploy-your-website-changes-using-git/. Look there for a more detailed explanation of what's going on.

此解决方案的功劳归功于http://sebduggan.com/blog/deploy-your-website-changes-using-git/。在那里查看有关正在发生的事情的更详细说明。