昨天,我发布了一个关于如何从我的一台机器克隆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版本)。这是一个可能的原因吗?


当前回答

我不得不在一个现有的裸库中重新运行git——init,这已经在裸库树中创建了一个.git目录-我意识到在那里输入git状态后。我把它删除了,一切又恢复正常了:)

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

其他回答

总结

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

由于裸存储库从来没有检出过任何分支,所以您总是可以推入裸存储库的任何分支。

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

解决方案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垃圾收集器的公平游戏。

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

我有一个在Git版本控制下的Xcode项目,我想把它推到DC中的虚拟分布式以太网(VDE)上。VDE运行Centos 5。

我读过的关于Git的文章中没有一篇谈到了裸库。这一切听起来都很简单,直到我尝试了我认为来自SVN背景的东西。

这里的建议使远程存储库裸露工作。更适合我的需求是克隆Xcode项目到projectname。Git,复制到远程服务器;然后,推神奇地起作用了。下一步将是让Xcode推送没有关于提交的错误,但现在我可以从终端做它。

So:

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字面上是项目的名称,但它可以是任何您愿意调用它的名称。少不更事的人不在乎,你会在乎的。

要使用scp,您需要在远程服务器上有一个允许SSH访问的用户帐户。任何运行自己服务器的人都会有这个。如果你正在使用共享主机或类似的东西,你可能就不走运了。

Remotehost.com是远程主机的名称。你可以使用它的IP地址。为了进一步清晰起见,我在远程主机上使用带有SSH密钥的giitosis,所以当我按下按钮时,不会提示输入密码。文章托管Git存储库,简单(和安全)的方式告诉你如何设置所有这些。

最好的方法是:

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

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

然后从本地Git存储库中:

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

进行更改后,您可以:

git push remoterepo master

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

git checkout --detach

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

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

当你去开发一个小程序时,这种事情就会发生。你要改变一些已经生效的东西,所以你施放了三级永久撤销法术:

machine1:~/proj1> git init

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

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

它会复制,一切看起来都很好,所以你可以从machine2上处理代码。

然后……您尝试从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 clone from 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 in it, it is meant to coordinate the commits from multiple sources. This is why the top-rated answer suggests deleting all files/folders other than the .git folder after you 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 status in 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和machine2上工作多少…

如果你已经完成了从machine1开始的开发,并将所有的开发都转移到machine2上……只需要做排名最高的答案所建议的:git config——bool core。完全正确,然后,可选地删除该文件夹中除.git之外的所有文件/文件夹,因为它们无法跟踪,可能会引起混乱。

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

如果你需要在machine1和machine2上继续开发……然后你需要正确地设置。您需要将您的repo转换为bare,然后您需要在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

非常重要:因为您已经将回购的位置从proj1移动到proj1。Git,您需要在machine2上的. Git /配置文件中更新它。之后,您可以从machine2提交更改。最后,我试着把我的裸回购放在一个中心位置,远离我的工作树(也就是说,不要把“proj1。Git '和'proj1'在同一个父文件夹中)。我建议您也这样做,但我想让上面的步骤尽可能简单。