ChatGPT解决这个技术问题 Extra ChatGPT

Git推送错误'[远程拒绝]主->主(当前已签出分支)'

昨天,我发布了一个关于如何将 Git 存储库从我的一台机器克隆到另一台机器的问题,How can I 'git clone' from another machine?

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

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

git push                                                
hap@192.168.1.2'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://hap@192.168.1.2/media/LINUXDATA/working
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'git+ssh://hap@192.168.1.2/media/LINUXDATA/working'

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

任何老前辈可以将接受的答案更改为 stackoverflow.com/a/9283833/397872 并将线程移动到存档或其他东西吗?或者改变所有权或其他什么?
实际上,您现在可以通过 Git 2.3.0(2015 年 2 月)和 git config receive.denyCurrentBranch=updateInstead 安全地推送到非裸存储库:stackoverflow.com/a/28262104/6309
这是@stigi 提到的这本书的新链接:git-scm.com/book/en/v1/Git-on-the-Server
但我不明白它为什么以及如何工作?它的工作,是的,但仅此而已。

M
Mikko Rantalainen

错误消息 error: refusing to update checked out branch: refs/heads/master 由远程存储库发出,这意味着您正在尝试将代码推送到当前在工作目录中签出不同代码的远程非裸存储库。避免此问题的最佳方法是仅推送到裸存储库 - 裸存储库永远不会发生此问题。

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

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

git config --bool core.bare true

然后删除该文件夹中除 .git 之外的所有文件。然后您将能够对远程存储库执行 git push 而不会出现任何错误。


谢谢。我也需要这个。我遵循 Git Community Book 中的子模块教程并遇到了这个障碍。
我不确定您是要删除服务器上的文件还是客户端上的文件...所以我没有删除任何内容,并且在执行 git config --bool core.bare true 后问题就消失了。是否有任何特殊原因需要删除某些文件?如果是这样,您能否更准确地了解需要删除的内容?
这是最好的答案,没有其他人在 Interwebs 中提供过它。我认为我们都在谷歌上搜索了相同的错误消息,并且我们都非常高兴地阅读了这篇文章。
尽管它获得了很多选票,但我认为这并不是对该特定问题的真正充分答案。指导用户如何干净地创建一个裸仓库会差一半,但是如果文件需要保持签出状态怎么办,例如当它是用户在两台计算机上使用的存储库时?
将源代码库更改为裸机是矫枉过正的。正如@Robert 指出的那样,您需要做的就是推送到源代码库中的新分支:stackoverflow.com/a/2933656/402949
P
Phil Dukhov

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

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

现在,您在工作存储库中并正在使用 master 分支。但是您也恰好在原始存储库中“登录”到同一个 master 分支。现在,由于您已经“登录”了原版,Git 担心您可能会搞砸,因为您可能正在处理原版并搞砸了。所以你需要回到原来的仓库做git checkout someotherbranch,现在你可以毫无问题地推送了。


+1 更有帮助,谢谢罗伯特。在我的情况下,我没有意义转换为裸回购。只需“停用”您尝试推送到的分支。说得通。
@FMaz008:只需创建一个虚拟分支(git checkout -b dummy)
伙计,这比大多数投票的答案要好得多:)谢谢。尽管另一个答案也很有意义:)
为了更清楚地说明这一点,在作为推送目标的 repo 中:git checkout -b tmp。然后在源代码库中:git push。然后返回目标(可选):git checkout master; git branch -d tmp
Hari 的评论是最简单的食谱。我只想说,虽然 git 在很多方面都很棒,来自 svn 或可能任何其他 rvs,但这整件事非常不直观。
C
CB Bailey

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

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

始终通过拉取(或获取并合并)来更新存储库,或者,如果必须,通过推送到单独的分支(导入分支)然后将该分支合并到远程计算机上的主分支中。

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

这将很容易意外提交撤消所有已推送更改的更改,并且很难区分尚未提交的任何本地更改和新 HEAD 之间的差异, 索引和工作树已经由 push 移动 HEAD 引起。


谢谢。那么我该如何解决我的问题呢?在我的 192 盒子里,我做了 '$ cd (project-directory) $ git init $ (add some files) $ git add .'然后在我的 191 框中,我做了一个“git clone”并编辑了一些文件,然后尝试“git push”。
好吧,我在回答中描述了可能性。您可以转到 192 框并从 191 框获取(您可能希望将 191 框添加为命名远程 - 查看 git remote add box191 <191url> ),或者您可以从 191 框推送到另一个命名的分支(例如git push origin master:refs/heads/upload ),然后到 192 框并合并(例如 git merge upload )。
实际上,您现在可以通过 Git 2.3.0(2015 年 2 月)和 git config receive.denyCurrentBranch=updateInstead:stackoverflow.com/a/28262104/6309 安全地推送到非裸仓库:您不再需要选项 2。
N
Nowhere man

概括

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

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

有多种解决方案,具体取决于您的需求。

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

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

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

现在您可以将所有想要的东西推送到与以前相同的地址。

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

但如果您需要查看远程 <remote> 上的代码,则可以使用特殊分支进行推送。假设在您的本地存储库中,您调用了远程 origin 并且您在分支 master 上。然后你可以做

machine2$ git push origin master:master+machine2

然后您需要在 origin 远程存储库中合并它:

machine1$ git merge master+machine2

问题的尸检

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

所以

A ← B
    ↑
[HEAD,branch1]

变成

A ← B ← C
        ↑
    [HEAD,branch1]

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

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

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

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

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


对“尸检”的一项技术更正:git 实际上不会在推送到的存储库中分离 HEADHEAD 仍将指向分支,而分支又将指向推送的新提交;但工作目录和索引/暂存区将保持不变。无论谁在推送到存储库上工作,现在都必须努力从推送的影响中恢复:弄清楚是否有任何更改要保存,如果有,请仔细安排保存它们。
要为您的答案添加更多信息,您希望人们推送到的远程存储库是非裸存储库的原因很少,因此使用裸存储库是最佳解决方案。
实际上,我发现了很多需要推送到非裸存储库的情况,并且我经常使用解决方案2。此外,我在非裸存储库上推送的分支绝不是临时分支,它的用途与远程跟踪分支相似。
我在我的服务器中创建了一个 GIT 文件夹,它将托管由多个用户使用 SourceTree 创建的所有存储库。我在本地 PC 中创建了一个 master 存储库。我将 remotes 添加到服务器文件夹并尝试将我的存储库推送到服务器中,以便其他用户可以拉/取它来处理它。我收到以下错误:! [remote rejected] master -> master (branch is currently checked out) 如何签入?
@SearchForKnowledge,你知道你问的正是我要回答的问题吗?!
A
Andre Holzner

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

[receive]
denyCurrentBranch = warn

或者

[receive]
denyCurrentBranch = false

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

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


使用它来将代码“部署”到服务器是行不通的。即使您禁用警告以便可以推送到签出的分支,工作副本也永远不会在推送时更新。
我正在使用上述方法和 cd .. && git reset --hard 接收后挂钩进行部署。 Hackish,但有效。
后者的命令行版本是 git config receive.denyCurrentBranch warn
这应该是公认的答案。我们中的一些人知道我们在做什么,而不是 Git 初学者。这就是那些人的答案。
哈,但问题不是那些人问的。
C
Ciro Santilli Путлер Капут 六四事

git config --local receive.denyCurrentBranch updateInstead

https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155

在服务器存储库上使用它,如果不会发生未跟踪的覆盖,它还会更新工作树。

它在 Git 2.3 中添加为评论中的 mentioned by VonC

我已经编译了 Git 2.3 并试了一下。示例用法:

git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead

cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git push origin master:master

cd ../server
ls

输出:

a
b

是的,b 被推了!


这对提交与服务器不是最新的更改有任何问题吗?
@akozi 我不确定您的意思,如果您在拉取之前在本地提交,它的行为将与传统的 --bare 克隆完全一样,我认为:--force 需要推送,它会让您“丢失”提交遥控器。
@CiroSantilli新疆改造中心六四事件法轮功 现在不用担心。我查了选项的含义。我认为 updateInstead 是力量的代名词。
updateInstead 不再是 receive.denyCurrentBranch 的有效值
@Xalorous 你有参考吗? github.com/git/git/blob/…
P
Peter Mortensen

我喜欢在远程机器上仍然有一个可用存储库的想法,但我喜欢使用以下方法而不是虚拟分支:

git checkout --detach

这似乎是 Git 的一个非常新的功能——我使用的是 git 版本 1.7.7.4。


然后在推送更改后,您可以使用:git checkout master 返回主分支。只有这样您的更改才会被应用。
P
Peter Mortensen

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

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

git config receive.denyCurrentBranch ignore

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

运行 Git 推送后,转到远程计算机并输入以下内容:

git checkout -f

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

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


感谢日志,我合并您的建议 denyCurrentBranch 并将 git checkout -f 放入 hooks 文件夹中,如 @jack-senechal 发布的 here
有没有办法让文件出现在远程存储库中而不去它并执行此命令?即通过当地的命令?
P
Peter Mortensen

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

在您的远程服务器上:

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

好的,从您当地的分支机构:

git push origin master:master

谢谢,这是我的解决方案,因为我在远程服务器上省略了“--bare”。这个问题的答案似乎取决于您是否将远程服务器存储库用作工作目录,对于后一种情况,这是正确的答案。
我不明白:SI 试图创建和克隆一个裸仓库,但克隆没有下载任何内容,也没有推送任何内容,所以这不起作用...... :-) 我阅读了关于裸仓库的教程,但他们说是一个裸仓库不包含文件...这绝对不是我要找的...
J
Jemenake

你可能做了什么导致这个:

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

machine1:~/proj1> git init

然后你开始添加/提交。但是随后,该项目开始参与更多,并且您想从另一台计算机(例如您的家用 PC 或笔记本电脑)上处理它,因此您可以执行以下操作

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

它克隆了,一切看起来都很好,所以你从 machine2 处理你的代码。

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

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

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

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

取决于您计划在 machine1 和 machine2 上工作多少...

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

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

如果您需要在 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

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


非常详细和有帮助。我的案子是最后一个案子,你的指示就像一个魅力。
我是案例 3,我做了一些稍微不同的事情: mk git-server; mv .git git-server/proj.git 然后 git clone git-server/proj.git 到 1 和 2(或 git remote origin ...),对机器 2 使用正确的 ssh:// 前缀。这样我将保留一个与 GH 或其他 HTTP 服务器上通常一样的裸主副本,并且我将继续在两台机器上使用推/拉。
J
Jack Senechal

通过几个设置步骤,您可以使用单线轻松将更改部署到您的网站,例如

git push production

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

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

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

然后创建文件 hooks/post-receive

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

并使文件可执行:

chmod +x hooks/post-receive

在您的本地机器上,

git remote add production git@myserver.com:mywebsite.git
git push production +master:refs/heads/master

可以了,好了!现在将来您可以使用 git push production 来部署您的更改!

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


您的建议对我帮助很大,但我没有使用 bare,我遵循 this 并与 hooks 合并(您建议)并且效果很好。
R
RibaldEddie

您应该只推送到裸存储库。裸仓库是没有签出分支的仓库。如果您要 cd 到一个裸存储库目录,您只会看到 .git 目录的内容。


推送到非裸存储库中的未签出分支没有任何问题。这是一种完全有效的工作方式。
很公平,那会奏效。但这不是用户正在做的事情。
这并不是说他没有使用“错误”的裸存储库。事实上,他正在推动一个已签出的分支。没有证据表明他拥有或想要一个单独的裸存储库,因此您一揽子声明他应该只推送到非裸存储库并没有为提问者提供所有选项;其中之一可能更容易解决他眼前的问题。
A
Arsen Khachaturyan

检查目标项目中的 .git/config

$ cat .git/config 
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[receive]
    denyCurrentBranch = updateInstead

如果 core. bare 为 false,您可以将其设置为 true:

$ git config core.bare true

然后在本地推送到远程:

git push remote_repo   // suppose the destination repo is remote_repo

它会成功,在 remote_repo 你可以检查 git 版本。

$ git log -1
commit 0623b1b900ef7331b9184722a5381bbdd2d935ba
Author: aircraft < aircraft_xxx@126.com>
Date:   Thu May 17 21:54:37 2018 +0800

现在你不能在你的“工作区”中使用 git:

$ git status
fatal: This operation must be run in a work tree

您应该将 bare.bare 设置回 false。

$ git config core.bare false

当我这样做时被覆盖有什么保护?
k
kenorb

你有3个选项

拉再推:git pull; git push 推送到不同的分支: git push origin master:foo 并在远程合并它(通过 git 或 pull-request) git merge foo 强制它(不推荐,除非你故意通过 rebase 更改提交): git push origin master -f如果仍然被拒绝,请禁用远程存储库上的denyCurrentBranch: git config receive.denyCurrentBranch ignore


选项 2 对我有用。远程 git init 本地 git push origin master:branch 远程 git merge DONE
s
sebthemonster

事实上,将远程设置为非签出分支就足够了。在不同的分支中签出遥控器后,您可以推送。


h
hobs

我在使用 Git 同步 Android 手机和笔记本电脑上的存储库时遇到了同样的问题。正如@CharlesBailey 建议的那样,我的解决方案是拉而不是推。

Android 存储库上的 git push origin master 对我来说失败,并出现与 @hap497 相同的错误消息,因为推送到存储库 + 工作副本的非裸签出。

git pull droid master 在笔记本电脑存储库中,工作副本对我有用。当然,您需要之前运行过 git remote add droid /media/KINGSTON4GB/notes_repo/ 之类的东西。


A
Andrew C

旧版本的 Git 曾经允许推送到非裸存储库的当前签出分支。

事实证明,这是一件非常令人困惑的事情。所以他们添加了你看到的警告信息,这也非常令人困惑。

如果第一个存储库只是充当服务器,则按照其他答案的建议将其转换为裸存储库并完成。

但是,如果您需要在两个都在使用的存储库之间有一个共享分支,您可以通过以下设置实现它

Repo1 - 将充当服务器,也用于开发

Repo2 - 仅用于开发

如下设置 Repo1

创建一个分支来共享工作。

git branch shared_branch

为了安全起见,您还应该创建一个 $(REPO).git/hooks/update 来拒绝对除了 shared_branch 之外的任何内容的任何更改,因为您不希望人们对您的私有分支进行处理。

repo1/.git/hooks  (GIT_DIR!)$ cat update
#!/bin/sh
refname="$1"
oldrev="$2"
newrev="$3"

if [ "${refname}" != "refs/heads/shared_branch" ]
then
   echo "You can only push changes to shared_branch, you cannot push to ${refname}"
   exit 1
fi

现在在 repo1 中创建一个本地分支,您将在其中进行实际工作。

git checkout -b my_work --track shared_branch
Branch my_work set up to track local branch shared_branch.
Switched to a new branch 'my_work'

(可能需要 git config --global push.default upstream 才能使 git push 工作)

现在您可以使用

git clone path/to/repo1 repo2 
git checkout shared_branch 

此时,您已将 repo1 和 repo2 设置为在从 repo1 中的 shared_branch 推送和拉取的本地分支上工作,而无需担心该错误消息或使工作目录在 repo1 中不同步。无论您使用什么正常的工作流程都应该有效。


P
Peter Mortensen

好的,如果你想要一个普通的远程存储库,那么创建一个额外的分支并检查它。将其推送到一个分支(未签出)中,然后在从本地推送后将其与当前处于活动状态的分支合并。

例如,在远程服务器上:

git branch dev
git checkout dev

在本地设置上:

git push 

在远程服务器上:

git merge dev

s
simo

这是您可以进行的一项测试,以了解 bare 服务器的工作原理:

想象一下,你有一个工作站和一个服务器,上面托管着实时站点,并且你想不时更新这个站点(这也适用于两个开发人员通过一个裸中间人来回发送他们的工作的情况)。

初始化

在本地计算机上创建一些目录并将 cd 放入其中,然后执行以下命令:

# initialization
git init --bare server/.git
git clone server content
git clone server local

首先,您创建一个裸服务器目录(注意最后的 .git)。此目录将仅用作存储库文件的容器。然后将您的服务器存储库克隆到新创建的内容目录。这是您的实时/生产目录,将由您的服务器软件提供服务。前两个目录位于您的服务器上,第三个是您工作站上的本地目录。

工作流程

现在这是基本的工作流程:

进入本地目录,创建一些文件并提交。最后将它们推送到服务器: # create crazy stuff git commit -av git push origin master 现在进入内容目录并更新服务器的内容: git pull 重复 1-2。这里的内容可能是另一个可以推送到服务器的开发人员,并且您可以从他那里拉取本地内容。


j
jontro

使用它将其推送到远程上游分支为我解决了这个问题:

git push <remote> master:origin/master

遥控器无法访问上游存储库,因此这是获取该遥控器最新更改的好方法


更一般地(因为这是命令的最终效果),使用 git push <remote> master:newbranch。这个想法是您将一个新分支推送到远程,然后可以将其合并。这样您就可以避免错误消息中提到的任何不一致问题。
P
Peter Mortensen

我不得不在现有的裸存储库中重新运行 git --init,这在裸存储库树中创建了一个 .git 目录 - 我在其中键入 git status 后意识到这一点。我删除了它,一切又好了:)

(所有这些答案都很棒,但就我而言,这是完全不同的(据我所知),如所述。)


p
pille

我相信大多数查看这个问题的人都会停留在前两个重要的答案上,但我仍然想提供我的解决方案。

遇到所描述的错误时,我有一个 Eclipse + EGit Web 项目设置。帮助我的是简单地使用 GitHub 应用程序,它似乎神奇地解决了这个问题。虽然 EGit 总是拒绝推送,但 GitHub 桌面应用程序只会耸耸肩并推送我的更改。也许它可以更优雅地处理多登录情况。


K
Korutech App Solutions

我发现一篇可能对其他人有用的文章是Git in 5 minutes

我有一个受 Git 版本控制的 Xcode 项目,我想将其推送到我在 DC 中的 Virtual Distributed Ethernet (VDE)。 VDE 运行 Centos 5。

我读过的关于 Git 的文章都没有谈到裸仓库。这一切听起来都很简单,直到我尝试了我认为应该很容易从 SVN 背景获得的东西。

此处使远程存储库裸露的建议有效。更符合我的要求是将 Xcode 项目克隆到 projectname.git,将其复制到远程服务器;然后推动神奇地工作。下一步将让 Xcode 推送而不会出现关于提交的错误,但现在我可以从终端执行此操作。

所以:

cd /tmp (or another other directory on your system)<br/>
git clone --bare /xcode-project-directory projectname.git<br/>
scp -r projectname.git sshusername@remotehost.com:repos/<br/>

在 Xcode 中提交后从 Xcode 项目推送更改:

cd /xcode-project-directory<br/>
git push sshusername@remotehost.com:repos/projectname.git<br/>

我敢肯定有一种更流畅更复杂的方式来完成上述操作,但至少这是可行的。一切都清楚了,这里有一些说明:/xcode-project-directory 是您的 xcode 项目存储的目录。它可能是 /Users/Your_Name/Documents/Project_Name。 projectname 字面意思是项目的名称,但它可以是任何您喜欢的名称。 Git 不在乎,你会的。

要使用 scp,您需要在远程服务器上拥有一个允许 SSH 访问的用户帐户。任何运行自己的服务器的人都会有这个。如果您使用的是共享主机等,您可能会不走运。

remotehost.com 是您的远程主机的名称。您可以轻松地使用其 IP 地址。为了更清楚起见,我在远程主机上使用了带有 SSH 密钥的 Gitosis,所以当我推送时不会提示我输入密码。文章Hosting Git Repositories, the Easy (and Secure) Way 告诉您如何设置所有这些。


B
Bill Donahue

最好的方法是:

mkdir ..../remote
cd ..../remote
git clone --bare .../currentrepo/

这将克隆存储库,但不会在 .../remote 中创建任何工作副本。如果您查看遥控器,您会看到创建了一个名为 currentrepo.git 的目录,这可能就是您想要的。

然后从本地 Git 存储库:

git remote add remoterepo ..../remote/currentrepo.git

进行更改后,您可以:

git push remoterepo master

r
rakslice

我刚刚在 Heroku 上的部署 git 存储库遇到了这个问题。

我不知道为什么 Heroku 有一个非裸存储库,但作为一种解决方法,我能够重置远程存储库并重新上传。

您不应该使用 Heroku 的存储库副本作为您唯一的 git 存储库进行协作,但以防万一,我会明确说明:除非您确定您的存储库的完整副本安全地存储在其他地方,否则不要这样做赫罗库。执行重置将删除存储库内容。

重置:

如果您还没有安装 Heroku 工具带(包含命令行客户端)。如果你还没有安装 heroku-repo 插件。 heroku 插件:安装 https://github.com/heroku/heroku-repo.git 执行重置,这将删除存储库并创建一个新的、空的 heroku repo:reset 像往常一样推送到您的 Heroku 远程;它会重新上传所有内容。


您可能需要安装 Heroku 存储库工具才能使其正常工作。做heroku plugins:install https://github.com/heroku/heroku-repo.git
v
vimal krishna

创建空(裸)存储库后,您将需要更改远程服务器上的配置文件,例如

root@development:/home/git/repository/my-project# cat config 

在那里你会看到

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

您将把它从假到真,我删除了 logallrefupdates = true (不确定它的用途!)

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

您可以测试以下

$ git remote show origin
* remote origin
Fetch URL: my-portal@development:/home/XYZ/repository/XYZ
Push  URL: my-portal@development:/home/XYZ/repository/XYZ
HEAD branch: (unknown)

如果您无法 PUSH,将显示此 HEAD 分支:(未知)。所以如果 HEAD 分支是未知的,你应该将 bare 更改为 true 并且推送成功后你可以重用

git remote show origin

你会看到

 HEAD branch: master

j
jmarceli

对我来说,工作解决方案是:

远程:

git checkout -b some_tmp_name

在本地:

git push

远程:

git checkout master
git branch -d some_tmp_name

但这不是真正的解决方案,它只是解决方法。


如果您没有中央存储库,这是一个有效的解决方案。
P
PbxMan

以防万一有人觉得它有用。对我来说,这是一个 git 服务器权限问题。我从一开始就检查了项目并推送了一个简单的文件,然后我得到了“推送被拒绝:推送到源/主服务器被拒绝”


L
Lyle Z

使用 Git,两个常规(非裸)存储库无法直接来回推送/拉取文件。必须有一个中间裸存储库。显然,这有点像一对有孩子的已婚夫妇,而这对夫妇正在离婚。父母不会互相交谈,但他们会通过孩子交流。

所以,你有一个存储库,你将这个存储库克隆到一个裸存储库,然后将它克隆到第三个。第一个和第三个可以通过第二个存储库(裸存储库)交换信息。我想这是有道理的,因为您不希望有人能够在未经您同意的情况下将内容签入您的存储库,因为这可能会导致合并冲突等。

所以,这里有一个例子:

在 PC 上,在 ~/workspace 中

git init
echo "line 1" > afile.txt
git add .
git commit -m ‘initial import’
git clone --bare . ../remote-repository.git
git remote add origin ../remote-repository.git
git push --set-upstream origin master

在笔记本电脑上,在 ~/workspace 中(不要执行 git init 等)

git clone //LJZ-DELLPC/remote-repository.git/ .

// 然后进行各种提交,并推送它们:

echo "line 2" > afile.txt
git add afile.txt
git commit -m 'added line 2'
git push    

然后回到 PC 上,在 ~/workspace

git pull

// 然后进行各种提交,并推送它们:

git push

在笔记本电脑上 git pull

等等..

这是一台机器上的一个绝对具体的例子,直接从命令窗口复制,这样我们就知道没有遗漏任何步骤,它确实有效,等等:

lylez@LJZ-DELLPC ~
$ cd gitdir
/home/lylez/gitdir

lylez@LJZ-DELLPC ~/gitdir
$ ls

lylez@LJZ-DELLPC ~/gitdir
$ mkdir repo1

lylez@LJZ-DELLPC ~/gitdir
$ cd repo1
/home/lylez/gitdir/repo1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git init
Initialized empty Git repository in /home/lylez/gitdir/repo1/.git/

lylez@LJZ-DELLPC ~/gitdir/repo1
$ echo "line 1" > afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git commit -m 'initial import'
[master (root-commit) f407e12] initial import
 1 file changed, 1 insertion(+)
 create mode 100644 afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git clone --bar . ../repo1-bare-clone
Cloning into bare repository '../repo1-bare-clone'...
done.

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git remote add origin ../repo1-bare-clone

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git push --set-upstream origin master
Branch master set up to track remote branch master from origin.
Everything up-to-date

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cd ..

lylez@LJZ-DELLPC ~/gitdir
$ ls
repo1  repo1-bare-clone

lylez@LJZ-DELLPC ~/gitdir
$ mkdir repo1-remote

lylez@LJZ-DELLPC ~/gitdir
$ cd repo1-remote
/home/lylez/gitdir/repo1-remote

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git clone ../repo1-bare-clone .
Cloning into '.'...
done.

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ echo "line 2" >> afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git commit -m 'added line 2'
[master 5ad31e0] added line 2
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 260 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /home/lylez/gitdir/repo1-remote/../repo1-bare-clone
   f407e12..5ad31e0  master -> master

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cd ../repo1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cat afile.txt
line 1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ../repo1-bare-clone
   f407e12..5ad31e0  master     -> origin/master
Updating f407e12..5ad31e0
Fast-forward
 afile.txt | 1 +
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cat afile.txt
line 1
line 2

lylez@LJZ-DELLPC ~/gitdir/repo1
$ echo "line 3" >> afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git commit -m 'added line 3'
[master 3fa569e] added line 3
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 265 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ../repo1-bare-clone
   5ad31e0..3fa569e  master -> master

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cd ../repo1-remote/

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1
line 2

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/lylez/gitdir/repo1-remote/../repo1-bare-clone
   5ad31e0..3fa569e  master     -> origin/master
Updating 5ad31e0..3fa569e
Fast-forward
 afile.txt | 1 +
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1
line 2
line 3

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git --version
git version 2.1.1

lylez@LJZ-DELLPC ~/gitdir/repo1-remote

这是一个有效的例子,并解释了为什么。除了您的评论之外,这里根本没有错误信息。
“使用 Git,两个常规(非裸)存储库不能直接来回推送/拉取文件” - 除了它们可以。
好吧,发布一个具体的例子而不是攻击。
或者你可以谷歌它? stackoverflow.com/questions/1764380/…
您站点的线程中的第一个响应以“...但是根据 git ready 和官方 git wiki,您应该只推送到一个裸仓库。”。下一个响应指出,“如果你想尝试只推送 master -> master,那么命令就是:git push origin”,这根本不起作用,并且有无数的帖子对此产生影响。最后一个响应以“我建议在您的服务器中拥有一个裸存储库和一个本地工作(非裸)存储库。”开头,这正是我的建议。
D
Daemon Painter

当我在我的 NAS 上克隆一个 repo 然后将该 repo 克隆到我的机器上时,我遇到了这个问题。

设置是这样的:

原始(github):

克隆到我的私人家庭网络(我的家庭网络)分支中的网络存储签出:开发

分支签出:开发

克隆到其他机器(笔记本电脑、我办公室的小型数据中心服务器等)分支已签出:开发

分支签出:开发

当我尝试从笔记本电脑提交到 NAS 服务器时,出现的错误是

! [remote rejected]   development -> development (branch is currently checked out)

根本原因是在 NAS 服务器上签出了 DEVELOPMENT 分支。我的解决方案是在 NAS 存储库上切换到任何其他分支。这让我可以提交我的更改。