昨天,我发布了一个关于如何将Git存储库从我的一台机器克隆到另一台机器的问题,如何从另一台机器"克隆"?.
我现在能够成功地将Git存储库从我的源(192.168.1.2)克隆到我的目标(192.168.1.1).
但是,当我对文件,a git commit -a -m "test"
和a 进行编辑时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).这是一个可能的原因吗?
您可以简单地将远程存储库转换为裸存储库(裸存储库中没有工作副本 - 该文件夹仅包含实际的存储库数据).
在远程存储库文件夹中执行以下命令:
git config --bool core.bare true
然后删除该文件.git
夹中的所有文件.然后,您将能够执行git push
远程存储库而不会出现任何错误.
我开始学习Git时,我遇到了同样的错误.其他一些答案显然不适合Git的新手!
(我将使用非技术术语来理解这个想法.)无论如何,发生的事情是你有两个存储库,一个是你最初创建的原始版本,另一个是你刚刚创建的工作版.
现在,您在工作存储库中并使用"主"分支.但是,您也恰好在原始存储库中"登录"到同一个"主"分支.既然你已经在原版中"登录"了,Git担心你可能会陷入困境,因为你可能正在研究原版并搞砸了.因此,您需要返回原始存储库并执行"git checkout someotherbranch",现在您可以毫无问题地推送.
我希望这有帮助.
错误消息描述了发生的情况.如果检出该分支,更多现代版本的Git拒绝通过推送更新分支.
在两个非裸存储库之间工作的最简单方法是
总是通过拉(或获取和合并)更新存储库,或者,如果必须,
通过推送到单独的分支(导入分支),然后将该分支合并到远程计算机上的主分支中.
这种限制的原因是推送操作仅在远程Git存储库上运行,它无法访问索引和工作树.因此,如果允许,对已签出分支的推送将更改为 HEAD
与远程存储库上的索引和工作树不一致.
这将使得很容易意外地提交撤消所有推送的更改的更改,并且很难区分尚未提交的任何本地更改以及新的HEAD
,索引和工作树之间的差异.由推动移动引起的HEAD
.
您无法推送到存储库的一个已检出分支,因为它会以最可能以数据和历史记录丢失而结束的方式弄乱该存储库的用户.但是您可以推送到同一存储库的任何其他分支.
由于裸存储库从未检出任何分支,因此您始终可以推送到裸存储库的任何分支.
根据您的需求,有多种解决方案.
如建议的那样,如果在一台计算机上,您不需要工作目录,则可以移至裸存储库.为避免弄乱存储库,您只需克隆它:
machine1$ cd .. machine1$ mv repo repo.old machine1$ git clone --bare repo.old repo
现在,您可以将所有想要的地址推送到与以前相同的地址.
但是如果您需要检查遥控器上的代码
,那么您可以使用特殊分支进行推送.假设您在本地存储库中调用了远程origin
控制器并且您在分支主控器上.然后你可以做到
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/config
目标服务器来解决此"限制" .添加以下内容以允许将git存储库推送到即使它被"签出":
[receive] denyCurrentBranch = warn
要么
[receive] denyCurrentBranch = false
第一个将允许推动,同时警告可能会弄乱分支,而第二个将静静地允许它.
这可以用于将代码"部署"到不用于编辑的服务器.这不是最好的方法,而是快速部署代码的方法.
git config --local receive.denyCurrentBranch updateInstead
https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155
在服务器存储库中使用它,如果不会发生未跟踪的覆盖,它还会更新工作树.
如VonC在评论中提到的那样,它被添加到Git 2.3 中.
我编译了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
被推了!
我喜欢在远程盒子上仍然有一个可用的存储库的想法,但我喜欢使用:而不是虚拟分支.
git checkout --detach
这似乎是Git的一个非常新的特性- 我使用的是git版本1.7.7.4.
我遇到过同样的问题.对我来说,我使用Git push将代码移动到我的服务器上.我从不更改服务器端的代码,所以这是安全的.
在存储库中,您正在推送键入:
git config receive.denyCurrentBranch ignore
这将允许您在存储库工作副本时更改存储库.
运行Git push后,转到远程计算机并键入:
git checkout -f
这将使您推送的更改反映在远程计算机的工作副本中.
请注意,如果您在要推送的工作副本中进行更改,这并不总是安全的.
您可以重新创建服务器存储库并从本地分支主服务器推送到服务器主服务器.
mkdir myrepo.git cd myrepo.git git init --bare
git push origin master:master
你可能做了什么导致这个:
当你去敲一个小程序时就会发生这种事情.你即将改变已经有效的东西,所以你施放了你永久无法解决的3级法术:
machine1:~/proj1> git init
然后你开始添加/提交.但是,然后,项目开始变得更加复杂,你想从另一台计算机(如你的家用电脑或笔记本电脑)上工作,所以你做了类似的事情
machine2:~> git clone ssh://machine1/~/proj1
它克隆,一切看起来都很好,所以你从machine2处理你的代码.
然后 ......你试图从机器2推送你的提交,你会在标题中收到警告信息.
这条消息的原因是因为您从中提取的git repo有点仅用于machine1上的该文件夹.你可以很好地克隆它,但推动可能会导致问题.在两个不同位置管理代码的"正确"方式是使用"裸"repo,就像已经建议的那样.裸回购没有设计有什么工作正在进行中,它是为了协调来自多个来源的提交.这就是为什么评价最高的答案建议删除除.git文件夹之外的所有文件/文件夹git config --bool core.bare true
.
澄清最受欢迎的答案:对该答案的许多评论都说"我没有从机器1中删除非.git文件,我仍然能够从机器2提交".那就对了.但是,那些其他文件现在完全与git repo"脱离"了.去尝试git status
那里,你应该看到像"致命:这个操作必须在工作树中运行"之类的东西.因此,删除文件的建议不是因为machine2的提交将起作用 ; 这样你就不会感到困惑,并认为git仍在跟踪这些文件.但是,如果您仍想处理machine1上的文件,删除文件是一个问题,不是吗?
那么,你应该怎么做?
取决于你计划在机器1和机器2上工作多少...
如果您已完成从machine1开发并将所有开发都移至machine2 ...只需执行评价最高的答案建议:git config --bool core.bare true
然后,可选地,从该文件夹中删除.git以外的所有文件/文件夹,因为它们没有跟踪,可能会造成混乱.
如果您在machine2上的工作只是一次性的事情,而且您不需要继续开发那么...那么就不要费心去做一个简单的回购; 只需ftp/rsync/scp/etc. 您的文件来自机器*2*在机器上的文件*1*,从机器*1*提交/推送,然后从机器*2*删除文件.其他人建议创建一个分支,但我认为如果你只是想在一次性的基础上合并一些开发来自另一台机器,那就太麻烦了.
如果您需要继续在machine1和machine2上进行开发......那么您需要正确设置.您需要将您的仓库转换为裸仓,然后您需要在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'相同的父文件夹中).我建议你这样做,但我想让上面的步骤尽可能简单.
通过一些设置步骤,您可以使用单线程轻松地将更改部署到您的网站
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/.在那里查看有关正在发生的事情的更详细说明.
你应该只是推到一个裸存储库.裸存储库是没有签出分支的存储库.如果你要cd到一个裸存储库目录,你只能看到.git目录的内容.
再拉一次:
git pull; git push
推入不同的分支:
git push origin master:foo
并将其合并到远程(通过git
或拉取请求)
git merge foo
强制它(除非你故意改变提交,否则不推荐rebase
):
git push origin master -f
如果仍然拒绝,请denyCurrentBranch
在远程存储库上禁用:
git config receive.denyCurrentBranch ignore
实际上,将远程设置为非签出分支就足够了.在另一个分支中检出您的遥控器后,您可以推送.
我在使用Git同步我的Android手机和笔记本电脑上的存储库时遇到了同样的问题.正如@CharlesBailey建议的那样,我的解决方案是做一次拉动而不是推动.
git push origin master
因为推送到存储库+工作副本的非正常结账,在Android存储库上失败了,因为@ hap497获得了相同的错误消息.
git pull droid master
在笔记本电脑存储库和工作副本为我工作.当然,你需要先运行类似的东西git remote add droid /media/KINGSTON4GB/notes_repo/
.
检查您.git/config
的目标项目:
$ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [receive] denyCurrentBranch = updateInstead
如果core. bare
false为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