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

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

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

但是当我编辑一个文件,一个git commit -a -m "test"和一个git push,我得到这个错误在我的目的地(192.168.1.1):

git pushhap@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/mastererror: By default, updating the current branch in a non-bare repositoryerror: is denied, because it will make the index and work tree inconsistenterror: with what you pushed, and will require 'git reset --hard' to matcherror: the work tree to HEAD.error:error: You can set 'receive.denyCurrentBranch' configuration variable toerror: 'ignore' or 'warn' in the remote repository to allow pushing intoerror: its current branch; however, this is not recommended unless youerror: arranged to update its work tree to match what you pushed in someerror: other way.error:error: To squelch this message and still keep the default behaviour, seterror: '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)。这是一个可能的原因吗?

606932 次浏览

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

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

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

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

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

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

这将使意外提交撤销所有推送更改的更改变得非常容易并且还使得区分任何尚未提交的本地更改以及新HEAD、索引和由推送移动HEAD引起的工作树之间的差异变得非常困难。

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

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

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

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

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

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

git config --bool core.bare true

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

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

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

[receive]denyCurrentBranch = warn

[receive]denyCurrentBranch = false

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

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

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

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

git config receive.denyCurrentBranch ignore

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

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

git checkout -f

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

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

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

在您的远程服务器上:

mkdir myrepo.gitcd myrepo.gitgit init --bare

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

git push origin master:master

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

git checkout --detach

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

我发现可能对其他人有用的一篇文章是5分钟后Git

我在Git版本控制下有一个Xcode项目,我想把它推到DC中的虚拟分布式以太网(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。project ectname是项目的字面意思,但它可以是任何你愿意称之为它的东西。Git不在乎,你会的。

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

remotehost.com是您的远程主机的名称。您可以很容易地使用它的IP地址。为了进一步清楚起见,我在远程主机上使用吉他斯,带有SSH键,所以我在推送时不会提示输入密码。文章托管Git存储库,简单(安全)的方式告诉您如何设置所有这些。

我在使用Git同步我的Android手机和笔记本电脑上的存储库时遇到了同样的问题。对我来说,解决方案是按照@CharlesBailey的建议进行拉取而不是推送。

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

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

这里有一个你可以做的测试,看看bare服务器的东西是如何工作的:

假设您有一个工作站和一个服务器,其中托管了实时站点,并且您希望不时更新此站点(这也适用于两个开发人员通过裸露的中间人来回发送他们的工作的情况)。

初始化过程

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

# initializationgit init --bare server/.gitgit clone server contentgit clone server local
  1. 首先,您创建一个裸server目录(注意末尾的. git)。该目录将仅用作存储库文件的容器。
  2. 然后将您的服务器存储库克隆到新创建的content目录。这是您的服务器软件将提供服务的实时/生产目录。
  3. 前两个目录驻留在服务器上,第三个是工作站上的本地目录。

工作流程

下面是基本的工作流程:

  1. 进入local目录,创建一些文件并提交。最后将它们推送到服务器:

    # create crazy stuffgit commit -avgit push origin master
  2. Now enter the content directory and update the server's content:

    git pull
  3. Repeat 1-2. Here content may be another developer that can push to the server too, and local as you may pull from him.

做到这一点的最佳方法是:

mkdir ..../remotecd ..../remotegit clone --bare .../currentrepo/

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

然后从您的本地Git存储库:

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

进行更改后,您可以:

git push remoterepo master

我必须在现有的裸存储库中重新运行git --init,这在裸存储库树中创建了一个.git目录-我在那里输入git status后意识到这一点。我删除了它,一切都恢复正常:)

(所有这些答案都很棒,但在我的情况下,这是完全不同的(据我所知),如所描述的。

通过一些设置步骤,您可以使用单行代码轻松地将更改部署到您的网站,例如

git push production

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

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

mkdir mywebsite.gitcd mywebsite.gitgit init --bare

然后创建文件hooks/post-receive

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

并使文件可执行:

chmod +x hooks/post-receive

在您的本地机器上,

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

一切就绪!现在将来您可以使用git push production来部署您的更改!

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

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

例如,在远程服务器上:

git branch devgit checkout dev

在本地设置中:

git push

在远程服务器上:

git merge dev

总结

您不能推送到存储库的一个签出分支,因为它会以最有可能以数据和历史丢失结尾的方式扰乱该存储库的用户。但您可以推送到同一存储库的任何其他分支。

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

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

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

按照建议,如果在一台机器上,你不需要工作目录,你可以移动到一个裸存储库。为了避免弄乱存储库,你可以克隆它:

machine1$ cd ..machine1$ mv repo repo.oldmachine1$ 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]

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

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

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

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

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

我的解决方案(使用中)

  1. 在远程服务器上签出“master”
  2. 本地工作在“dev”分支
  3. 将更改推送到远程开发
  4. 将dev合并到远程主机

答对了

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

在远程:

git checkout -b some_tmp_name

关于本地:

git push

在远程:

git checkout mastergit branch -d some_tmp_name

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

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

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

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

要重置:

  1. 如果尚未安装,请安装Heroku工具带(其中包含命令行客户端)。
  2. 如果还没有安装,请安装heroku-repo插件

    heroku plugins:install https://github.com/heroku/heroku-repo.git
  3. Do the reset, which deletes the repository and creates a new, empty one

    heroku repo:reset
  4. Push to your Heroku remote as you normally would; it will reupload everything.

有了Git,两个普通(非裸)仓库不能直接来回推/拉文件。必须有一个中介裸仓库。显然,这有点像一对有孩子的已婚夫妇,这对夫妇正在离婚。父母不会互相交谈,但他们会通过孩子沟通。

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

所以,这里有一个例子:

在PC上,在~/workspace

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

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

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

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

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

然后回到PC,在~/workspace

git pull

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

git push

在笔记本电脑上git拉取

等等…

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

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 initInitialized 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 import1 file changed, 1 insertion(+)create mode 100644 afile.txt
lylez@LJZ-DELLPC ~/gitdir/repo1$ git clone --bar . ../repo1-bare-cloneCloning 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 masterBranch master set up to track remote branch master from origin.Everything up-to-date
lylez@LJZ-DELLPC ~/gitdir/repo1$ cd ..
lylez@LJZ-DELLPC ~/gitdir$ lsrepo1  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$ lsafile.txt
lylez@LJZ-DELLPC ~/gitdir/repo1-remote$ cat afile.txtline 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 21 file changed, 1 insertion(+)
lylez@LJZ-DELLPC ~/gitdir/repo1-remote$ git pushCounting 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-clonef407e12..5ad31e0  master -> master
lylez@LJZ-DELLPC ~/gitdir/repo1-remote$ cd ../repo1
lylez@LJZ-DELLPC ~/gitdir/repo1$ lsafile.txt
lylez@LJZ-DELLPC ~/gitdir/repo1$ cat afile.txtline 1
lylez@LJZ-DELLPC ~/gitdir/repo1$ git pullremote: Counting objects: 3, done.remote: Total 3 (delta 0), reused 0 (delta 0)Unpacking objects: 100% (3/3), done.From ../repo1-bare-clonef407e12..5ad31e0  master     -> origin/masterUpdating f407e12..5ad31e0Fast-forwardafile.txt | 1 +1 file changed, 1 insertion(+)
lylez@LJZ-DELLPC ~/gitdir/repo1$ cat afile.txtline 1line 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 31 file changed, 1 insertion(+)
lylez@LJZ-DELLPC ~/gitdir/repo1$ git pushCounting 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-clone5ad31e0..3fa569e  master -> master
lylez@LJZ-DELLPC ~/gitdir/repo1$ cd ../repo1-remote/
lylez@LJZ-DELLPC ~/gitdir/repo1-remote$ lsafile.txt
lylez@LJZ-DELLPC ~/gitdir/repo1-remote$ cat afile.txtline 1line 2
lylez@LJZ-DELLPC ~/gitdir/repo1-remote$ git pullremote: 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-clone5ad31e0..3fa569e  master     -> origin/masterUpdating 5ad31e0..3fa569eFast-forwardafile.txt | 1 +1 file changed, 1 insertion(+)
lylez@LJZ-DELLPC ~/gitdir/repo1-remote$ cat afile.txtline 1line 2line 3
lylez@LJZ-DELLPC ~/gitdir/repo1-remote$ git --versiongit version 2.1.1
lylez@LJZ-DELLPC ~/gitdir/repo1-remote

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

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

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

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

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

Repo2-仅用于开发

设置Repo1如下

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

git branch shared_branch

为了安全起见,您还应该创建一个$(REPO). git/Hooks/Update,它拒绝对shared_branch以外的任何更改,因为您不希望人们破坏您的私有分支。

repo1/.git/hooks  (GIT_DIR!)$ cat update#!/bin/shrefname="$1"oldrev="$2"newrev="$3"
if [ "${refname}" != "refs/heads/shared_branch" ]thenecho "You can only push changes to shared_branch, you cannot push to ${refname}"exit 1fi

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

git checkout -b my_work --track shared_branchBranch 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工作)

现在你可以创建repo2

git clone path/to/repo1 repo2git checkout shared_branch

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

git config --local receive.denyCurrentBranch updateInstead

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

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

它在git2.3中被添加为评论中的VonC提到

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

git init servercd servertouch agit add .git commit -m 0git config --local receive.denyCurrentBranch updateInstead
cd ..git clone server localcd localtouch bgit add .git commit -m 1git push origin master:master
cd ../serverls

输出:

ab

b被推了!

以防有人发现它很有用。对我来说,这是一个git服务器权限问题。我从请求中签出了项目并推送了一个简单的文件,然后我得到了“推送被拒绝:推送到源/主被拒绝”

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

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

在那里你会看到

[core]repositoryformatversion = 0filemode = truebare = falselogallrefupdates = true

你会让这个裸露到假到真,我删除了logallrepudates=true(不确定它的用途!)

[core]repositoryformatversion = 0filemode = truebare = true

您可以测试以下内容

$ git remote show origin* remote originFetch URL: my-portal@development:/home/XYZ/repository/XYZPush  URL: my-portal@development:/home/XYZ/repository/XYZHEAD branch: (unknown)

如果您无法推送,将显示此HEAD分支:(未知)。因此,如果HEAD分支未知,您应该将裸更改为true,推送成功后,您可以重复使用

git remote show origin

你会看到

 HEAD branch: master

你有三个选择

  1. 再次拉和推:

    git pull; git push
  2. Push into different branch:

    git push origin master:foo

    并在远程合并它(通过git拉取请求

    git merge foo
  3. Force it (not recommended unless you deliberately changed commits via rebase):

    git push origin master -f

    如果仍然拒绝,请禁用denyCurrentBranch远程存储库:

    git config receive.denyCurrentBranch ignore

你可能做了什么导致了这一点:

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

machine1:~/proj1> git init

然后你开始添加/提交。但是然后,项目开始变得越来越复杂,你想从另一台电脑(比如你的家用电脑或笔记本电脑)上处理它,所以你做了这样的事情

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

它克隆,一切看起来都很好,所以你从机器2上处理你的代码。

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

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

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

那么,你真正应该做什么?

这取决于你计划在机器1和机器2上工作多少…

如果您完成了从机器1的开发并将所有开发移至机器2…只需按照最受好评的答案进行操作:git config --bool core.bare true,然后可选地从该文件夹中删除除. git之外的所有文件/文件夹,因为它们未被跟踪并且可能导致混乱。

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

如果您需要在机器1和机器2上继续开发…然后您需要正确设置。您需要将您的存储库转换为裸存储库,然后您需要在机器1上复制它以供您工作输入。可能最快的方法是这样做

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

非常重要:,因为你已经将存储库的位置从项目1移动到proj1.git,您需要在机器2上的. git/config文件中更新此文件。之后,你可以从机器2提交你的更改。最后,我试着把我的裸存储库放在一个中心位置,远离我的工作树(即不要把proj1.git和项目1放在同一个父文件夹中)。我建议你也这样做,但我想让上面的步骤尽可能简单。

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

$ cat .git/config[core]repositoryformatversion = 0filemode = truebare = falselogallrefupdates = 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 -1commit 0623b1b900ef7331b9184722a5381bbdd2d935baAuthor: aircraft < aircraft_xxx@126.com>Date:   Thu May 17 21:54:37 2018 +0800

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

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

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

$ git config core.bare false

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

git push <remote> master:origin/master

远程无法访问上游存储库,因此这是将最新更改放入远程的好方法

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

设置是这样的:

原始(github):

  • 克隆到我的私人家庭网络(我的家庭网络)中的网络存储
    • 已签出分支:DEVELOPMENT
  • 克隆到其他机器(笔记本电脑,我办公室的小型数据中心服务器等)
    • 已签出分支:DEVELOPMENT

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

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

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

让我加上我的50美分,因为投票最多的答案https://stackoverflow.com/a/3251126/3455918建议将远程repw转换为裸存储库,如果这不是我想要的怎么办?

最后,我必须在远程机器上拥有相同的代码,而不仅仅是. git林博中某个地方的字节块。

第二次投票(在撰写本文时)的解决方案https://stackoverflow.com/a/2933656/3455918完成了这项工作,但在测试之后,我最终不得不在远程机器上的分支之间不断切换,以“释放”我想从本地机器推送到的分支。

这对我有效:

到目前为止,另一个对我有效的解决方案不是我的,归功于对第一个解决方案发表评论的用户@kxr。

在远程机器上,您必须在repo目录中执行此命令。

git config receive.denyCurrentBranch updateInstead

在这之后,你完成了!

显然,此解决方案可能存在一些缺点,但对于将本地机器代码同步到远程存储库的简单任务来说,它可能已经足够好了。

如果有人在评论中解释为什么在github上创建一个全新的repo,将您的本地文件夹链接到它并开始执行git push origin master而没有错误,我将不胜感激。

但是尝试在远程服务器上使用repo做同样的事情会产生错误:

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