昨天,我发布了一个关于如何从我的一台机器克隆Git存储库到另一台机器的问题,我如何从另一台机器“克隆Git”?
现在我可以成功地将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版本)。这是一个可能的原因吗?
下面是一个测试,你可以看看裸服务器的东西是如何工作的:
想象一下,您有一个工作站和一个服务器,服务器上托管着活动站点,您希望不时地更新这个站点(这也适用于两个开发人员通过一个中间人来回发送他们的工作的情况)。
初始化
在你的本地计算机上创建一个目录,并将cd放入其中,然后执行以下命令:
# initialization
git init --bare server/.git
git clone server content
git clone server local
首先创建一个裸服务器目录(注意末尾的.git)。此目录将仅作为存储库文件的容器。
然后将服务器存储库克隆到新创建的内容目录。这是您的活动/生产目录,将由服务器软件提供服务。
前两个目录位于您的服务器上,第三个是您工作站上的本地目录。
工作流
下面是基本的工作流程:
进入本地目录,创建一些文件并提交。最后将它们推送到服务器:
#创造疯狂的东西
Git提交-av
Git push origin master
现在进入内容目录并更新服务器的内容:
git拉
重复1 - 2。这里的内容可能是另一个开发人员也可以推送到服务器上的,并且您可以从他那里获取本地内容。
下面是一个测试,你可以看看裸服务器的东西是如何工作的:
想象一下,您有一个工作站和一个服务器,服务器上托管着活动站点,您希望不时地更新这个站点(这也适用于两个开发人员通过一个中间人来回发送他们的工作的情况)。
初始化
在你的本地计算机上创建一个目录,并将cd放入其中,然后执行以下命令:
# initialization
git init --bare server/.git
git clone server content
git clone server local
首先创建一个裸服务器目录(注意末尾的.git)。此目录将仅作为存储库文件的容器。
然后将服务器存储库克隆到新创建的内容目录。这是您的活动/生产目录,将由服务器软件提供服务。
前两个目录位于您的服务器上,第三个是您工作站上的本地目录。
工作流
下面是基本的工作流程:
进入本地目录,创建一些文件并提交。最后将它们推送到服务器:
#创造疯狂的东西
Git提交-av
Git push origin master
现在进入内容目录并更新服务器的内容:
git拉
重复1 - 2。这里的内容可能是另一个开发人员也可以推送到服务器上的,并且您可以从他那里获取本地内容。
让我加上我的50美分,因为投票最多的答案https://stackoverflow.com/a/3251126/3455918建议将远程repw转换为裸库,如果这不是我想要的呢?
最后,我必须在远程机器上有相同的代码,但不只是.git边缘的某个地方的一团字节。
第二次投票(在撰写本文时)的解决方案https://stackoverflow.com/a/2933656/3455918可以完成这项工作,但在测试之后,我最终不得不不断地在远程机器上的分支之间切换,以“释放”我想从本地机器推送到的分支。
这招对我很管用:
到目前为止对我有效的另一个解决方案不是我的,功劳是给了一个对第一个解决方案发表评论的用户@kxr。
在远程机器上,您必须在repo目录中执行此命令。
git配置receive.denyCurrentBranch updateInstead
在此之后,您就完成了!
显然,这种解决方案可能有一些缺点,但对于将本地机器代码同步到远程回购的简单任务来说,它可能已经足够好了。
如果有人在评论中解释为什么在github上创建一个全新的repo,将你的本地文件夹链接到它,并开始做git push origin master而没有错误,我会很感激。
但是尝试在远程服务器上进行同样的回购会产生错误:
! [远程拒绝]master -> master(分支当前签出)
总结
您不能推送到存储库的一个签出分支,因为这会扰乱该存储库的用户,很可能以丢失数据和历史记录而告终。但是您可以推送到同一存储库的任何其他分支。
由于裸存储库从来没有检出过任何分支,所以您总是可以推入裸存储库的任何分支。
根据您的需要,有多种解决方案。
解决方案1:使用裸存储库
正如建议的那样,如果在一台机器上不需要工作目录,则可以移动到裸存储库。为了避免混淆存储库,你可以克隆它:
machine1$ cd ..
machine1$ mv repo repo.old
machine1$ git clone --bare repo.old repo
现在你可以把所有你想要的推送到和以前一样的地址。
解决方案2:推到一个非签出分支
但是如果您需要检出remote <remote>上的代码,那么您可以使用一个特殊的分支来进行推送。假设在本地存储库中,您已经调用了远程源,并且处于分支master上。然后你就可以
machine2$ git push origin master:master+machine2
然后你需要合并它当你在原始远程回购:
machine1$ git merge master+machine2
问题的解剖
当一个分支签出时,提交将添加一个新的提交,当前分支的头作为其父,并移动该分支的头作为新提交。
So
A ← B
↑
[HEAD,branch1]
就变成了
A ← B ← C
↑
[HEAD,branch1]
但如果有人可以推送到中间的那个分支,用户就会进入git所说的分离头部模式:
A ← B ← X
↑ ↑
[HEAD] [branch1]
现在用户不再在branch1中,没有显式地要求签出另一个分支。更糟糕的是,用户现在在任何分支之外,任何新的提交都会悬空:
[HEAD]
↓
C
↙
A ← B ← X
↑
[branch1]
假设,如果此时用户签出了另一个分支,那么这个悬空提交将成为Git垃圾收集器的公平游戏。