我克隆了一个远程repo,并希望在本地git服务器上有一个自己的副本。
所以我做了:
git clone ssh...
我在我的服务器上创建了一个新的回购
git init --bare
我添加了新的服务器
git remote add bm ssh...
然后我推到新的远程
git push --mirror bm
现在我可以在我的裸服务器回购上看到:
[gitmini@blaumeise simulavr]$ git branch -a
* master
remotes/bm/master
remotes/savannah/HEAD
remotes/savannah/devel-tomk
remotes/savannah/master
remotes/savannah/oldstable
remotes/savannah/python_3
remotes/savannah/rel-1.0
remotes/savannah/rel-1.1
remotes/savannah/sbi_cbi_rework
我觉得看起来不错。
但现在我从本地服务器上注销了
git clone ssh...
我只得到:
git branch -a
[krud@blaumeise simulavr]$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
我已经做了:git fetch --all
和git pull --all
,没有任何变化。
我自己的服务器repo有什么问题吗?或者克隆时有什么问题?在这样糟糕的情况下我能做什么。
我已经阅读:如何获取所有Git分支
git clone
默认只复制其他Git的(本地)分支和标记。可以获取其他引用,包括remotes/savannah/oldstable
等远程跟踪名称。但这通常不是一个好主意。相反,在您的裸存储库中,使it具有具有这些名称的分支。
起初这一切都有点棘手,但最终一切都开始有意义了。这些名称源于使用两个独立的Git存储库。每个Git存储库都有自己的分支名称,因此:
-
分支名称是一个全名以
refs/heads/
开头的引用。所以refs/heads/master
表示分支master
,依此类推 -
远程跟踪名称是全名以
refs/remotes/
开头的引用。全名的下一部分与远程的名称相同,之后(和另一个斜杠)您将获得来自其他Git的分支名称。
这是正常克隆的正常使用模式。有一些现有的存储库,一些人或许多人已经在网络上的某个地方(例如,在GitHub上)建立了它,它有很多分支:master
、develop
、feature/A
、feature/B
等等。你可以将该存储库克隆到你自己的机器(笔记本电脑或其他什么)上,并希望让你的Git记住他们的分支,而不是创建一堆(本地)分支。现在,您可能选择做一些工作,稍后将其作为feature/A
的一部分发送给他们,因此您创建自己的名称feature/A
,在其上进行新的提交以发送给他们并建议他们将这些提交放在的feature/A
中。您根本没有使用feature/B
,因此没有获得feature/B
,也没有使用master
,因此可以删除自己的master
。
一旦有了一些新的提交,您将使用:
git push origin feature/A
将您的新提交发送到他们的Git,并立即作为git push
本身的一部分,要求他们的Git设置的feature/A
分支来记住这些新提交。
这不是你想要的
当您第一次设置集中式服务器存储库时,您通常不希望遵循正常模式。您已经或者想要复制一些现有的存储库,比如说,有十几个分支名称。如果您自己的笔记本电脑上还没有这个存储库,您可以使用git clone --mirror
在自己的笔记本上制作一个临时副本:
git clone --mirror <url> [<path>]
现在,您的笔记本电脑上有一个裸克隆(--mirror
表示--bare
),它根本没有origin/*
远程跟踪名称。相反,Git在其存储库的副本中创建了与分支名称相对应的常规旧分支名称,而不是远程跟踪名称。因此,有与其相同的十几个分支名称。
镜像克隆对你自己做任何工作都没有用您临时创建此镜像克隆,以获取其存储库的副本,其中的分支名称也是您的分支名称。如果您已经有一个完整的工作存储库,其中包含十几个(或其他)分支,则跳过此步骤。
现在您有了包含所有分支的克隆,现在您可以在服务器(或GitHub)上创建一个空存储库现在您可以运行:
git push --all <url-of-server-repository>
现在,如果您制作了镜像克隆,您可以丢弃镜像克隆。您创建它只是为了将所有内容(包括所有分支名称)发送到服务器。因此,现在您可能需要删除镜像克隆,并制作服务器克隆的正常克隆以用于执行实际工作。
(如果您从已经全部设置好的本地存储库中执行了git push
,则不希望或不需要删除本地克隆,并且您可能希望在git push
之前使用git remote add
。请参阅下文。)
以上内容有些浪费
您可能会反对必须制作这个愚蠢的镜像克隆,但在将镜像克隆推送到服务器后,必须将其丢弃并制作一个正常的非裸克隆。
您不必制作镜像克隆。这只是为了方便。
相反,您可以:
- 制作常规克隆
- 根据需要创建本地分支,以表示所有远程跟踪名称
- 使用
git push --all
将这些全部发送到服务器 - 删除所有您创建的本地名称(但保留任何您不必创建的名称)
或者,您可以:
- 制作(或拥有)常规克隆
- 使用不带
--all
的git push
:相反,使用refspecs将您端的远程跟踪名称推送到其端的分支名称
最后一种方法在某些方面是最整洁的,但它需要理解refspec。
refspec的第二种最简单的形式是一对引用——像refs/heads/master
或refs/remotes/feature/A
这样的全名——用冒号:
分隔。冒号左侧的名称是源,右侧的名称是目标。Refspecs在git fetch
和git push
中的行为相似,但并不完全相同:源ref在发送Git中提供提交哈希,目标ref提供要在接收Git中设置的名称。由于git push
从您的Git存储库发送到他们的Git存储,您可以在左侧使用您的远程跟踪名称,在右侧使用他们的分支名称:
# after creating an empty repository on github
git remote add origin <url-on-github>
git push origin master # send your refs/heads/master to theirs
git push origin refs/remotes/savannah/devel-tomk:refs/heads/devel-tomk
git push origin refs/remotes/savannah/python_3:refs/heads/python_3
(假设您希望您的远程跟踪savannah/devel-tomk
成为他们的devel-tomk
分支,依此类推)。
你可以把所有的refspec放在一个大的git push
行中,但它的一部分很容易拼写错误,这很烦人:
git push origin master refs/remotes/savannah/devel-tomk:refs/heads/devel-tomk refs/remotes/savannah/python_3:refs/heads/python_3
例如,如果我没有错别字的话。
您没有创建整个repo的副本。您只创建了一个带有master分支的repo。
默认情况下,push只推送一个分支。尝试添加--all
标志
git push --mirror --all bm