Git克隆已经是克隆的存储库

dr_*_*_rk 9 git git-clone

我不确定这是否是一个愚蠢的问题,但有没有任何不良的副作用来做一个git clone已经克隆另一个远程存储库的存储库?

kos*_*tix 13

没有副作用,但您应该准确了解克隆存储库时会发生什么.

一些理论

"问题"是当您以"正常方式"克隆存储库时 - 也就是说,在调用时没有调整任何时髦的旋钮git clone- 您最终没有与源库相同的存储库.它确实包含完全相同的历史,但它具有不同的分支布局.

为了以非科学的方式解释它,让我们举一个例子:

  1. 源仓库包含分支"master","dev"和"release".

    它还包含两个标签,"v1"和"v2".

    该存储库中的"HEAD"引用指向分支"master".

  2. 克隆此repo时,您的本地克隆将具有:

    • 三个远程跟踪分支:"origin/master","origin/dev"和"origin/release".

    • 两个标签"v1"和"v2".

    • 一个地方命名为"主"分支指向同一个commit,远程跟踪分支"origin/master的"一样.

  3. 如果您现在克隆此克隆,结果将具有:

    • 单个远程跟踪分支"origin/master".

    • 单个本地分支"主".

    • 两个标签"v1"和"v2".

这可能看起来很奇怪,但实际上这在手册页中有明确说明:

将存储库克隆到新创建的目录中,为克隆存储库中的每个分支创建远程跟踪分支(可见使用git branch -r),并创建并检出从克隆存储库的当前活动分支分叉的初始分支.

克隆之后,没有参数的普通git fetch将更新所有远程跟踪分支,并且没有参数的git pull将另外将远程主分支合并到当前主分支中(如果有的话)(这在"--single"时是不真实的-branch"给出;见下文).

此默认配置是通过在refs/remotes/origin初始化 remote.origin.urlremote.origin.fetch配置变量下创建对远程分支头的引用来实现的.

因此,"克隆" git clone意味着克隆了所有历史记录(除非另有说明),但分支的布局是不同的.

原因是这样的:完全是因为 Git是一个分布式VCS,非裸存储库中的所有分支都是"你的",因为你对它们有效,只有你决定它们如何与其他存储库中的分支同步,为什么

所以当你克隆一个回购"正常的方式"Git:

  • 仅获取该存储库的本地分支:不会查询远程跟踪分支.

    这是因为远程跟踪分支用作其他存储库状态的书签,并且没有对它们进行任何工作.

    要理解为什么Git会以这种方式运行,请考虑在您希望Joe工作时克隆Joe的存储库,而不是从他与之通信的任何随机存储库中获取的东西.

  • 将所有获取的分支转换为生成的repo中的远程跟踪分支.

  • 创建一个本地分支并将其签出.

    这仅仅是一种便利,只会增加可能的混淆.

该怎么办

好吧,git clone接受一个"--mirror"命令行选项,它生成一个原始仓库的真实副本,但生成的仓库将是裸的.如果使用"--mirror"命令行选项再次重新克隆生成的repo,您​​将再次获得真正的副本.

如果你做了一个"普通"克隆(我认为,你做了),你仍然可以从该存储库中获取所有内容,但git clone不会删除它:你需要做git init后面git remote add origin <url> 跟着一个特制的git fetch.

究竟如何制作git fetch,取决于你真正想从源回购中获取什么,以及在哪里放置它.首先,请考虑源repo现在具有"origin/master"和"master",并且它们可能包含不同的历史记录.

还要注意克隆一个非裸的repo使用git clone --mirror会起作用,但结果不会很明智,因为在这种情况下git clone将尽职地复制所有分支 - 本地和远程跟踪 - 来自源repo 逐字和远程跟踪分支不是你通常希望在一个简单的回购中出现的东西.