git clone -mirror和git clone -bare的区别是什么

git克隆帮助页面有这样说--mirror:

设置远程存储库的镜像。这意味着--bare

但是没有详细说明--mirror克隆与--bare克隆的不同之处。

414990 次浏览
$ git clone --mirror $URL

速记是为了什么

$ git clone --bare $URL
$ (cd $(basename $URL) && git remote add --mirror=fetch origin $URL)

(直接从在这里复制)

当前的手册是这么说的:

--bare相比,--mirror不仅将源的本地分支映射到目标的本地分支,它还映射了所有的引用(包括远程分支,注释等),并设置了一个refspec配置,以便所有这些引用都被目标存储库中的git remote update覆盖。

不同的是,当使用--mirror时,所有引用将被复制按原样。这意味着一切:远程跟踪分支,注释,参考/原始/*(从过滤器分支备份)。克隆的回购拥有一切。它还被设置为远程更新将从原点重新获取所有内容(覆盖复制的引用)。这个想法实际上是镜像存储库,有一个完整的副本,这样你就可以在多个地方托管你的中央回购,或者备份它。考虑直接复制回购,只是以一种更优雅的git方式。

新的文档基本上说明了这一切:

# EYZ0

设置源存储库的镜像。这意味着--bare。与--bare相比,--mirror不仅将源的本地分支映射到目标的本地分支,它还映射了所有的引用(包括远程分支,注释等),并设置了一个refspec配置,以便所有这些引用都被目标存储库中的git remote update覆盖。

我最初的回答还指出了裸克隆和正常(非裸)克隆之间的区别——非裸克隆设置远程跟踪分支,只为HEAD创建一个本地分支,而裸克隆直接复制分支。

假设原点有一些分支(master (HEAD)nextpumaint),一些标签(v1v2v3),一些远程分支(devA/masterdevB/master)和一些其他的引用(refs/foo/barnext0,可能是笔记,存储,其他开发人员的名称空间,谁知道呢)。

  • git clone origin-url(非裸):你将得到所有的标签复制,一个本地分支master (HEAD)跟踪一个远程分支origin/master,和远程分支origin/nextorigin/puorigin/maint。跟踪分支的设置是这样的,如果您执行git fetch origin之类的操作,它们将按照您的期望获取。任何远程分支(在克隆的远程中)和其他引用都被完全忽略。

  • 你将得到所有的标签复制,本地分支master (HEAD)nextpumaint,没有远程跟踪分支。也就是说,所有的分支都被原样复制,并且它被完全独立地设置,不期望再次获取。任何远程分支(在克隆的远程中)和其他引用都被完全忽略。

  • git clone --mirror origin-url:这些引用中的每一个都将按原样复制。你会得到所有的标签,本地分支master (HEAD)nextpumaint,远程分支devA/masterdevB/master,其他参考refs/foo/barrefs/foo/baz。一切都和克隆的远程中完全一样。远程跟踪设置,所以如果你运行git remote update,所有的引用将从原点覆盖,就像你刚刚删除了镜像并重新克隆它一样。就像医生最初说的,这是一面镜子。它应该是一个功能完全相同的副本,可以与原件互换。

一个克隆复制的裁判从远程和stuff他们到一个子目录名为“这些是裁判,远程拥有”。

镜像从远程复制裁判,并把他们放在自己的顶级-它替换自己的裁判与那些远程。

这意味着当有人从你的镜像中提取并将镜像的引用放入他们的子目录时,他们将得到与原始镜像相同的引用。从最新镜像中获取的结果与直接从初始回购中获取的结果相同。

我今天对git-2.0.0的测试表明——mirror选项没有复制钩子、配置文件、描述文件、info/exclude文件,至少在我的测试用例中没有复制一些引用(我不理解)。我不会称它为“功能完全相同的副本,可以与原件互换”。

-bash-3.2$ git --version
git version 2.0.0
-bash-3.2$ git clone --mirror /git/hooks
Cloning into bare repository 'hooks.git'...
done.


-bash-3.2$ diff --brief -r /git/hooks.git hooks.git
Files /git/hooks.git/config and hooks.git/config differ
Files /git/hooks.git/description and hooks.git/description differ
...
Only in hooks.git/hooks: applypatch-msg.sample
...
Only in /git/hooks.git/hooks: post-receive
...
Files /git/hooks.git/info/exclude and hooks.git/info/exclude differ
...
Files /git/hooks.git/packed-refs and hooks.git/packed-refs differ
Only in /git/hooks.git/refs/heads: fake_branch
Only in /git/hooks.git/refs/heads: master
Only in /git/hooks.git/refs: meta

关于复制存储库的GitHub文档有一个微妙的解释:

与裸克隆一样,镜像克隆包括所有远程分支和标记,但每次获取时都会覆盖所有本地引用,因此它始终与原始存储库相同。

我添加了一张图片,显示# eyz0镜像和裸之间的差异。 enter image description here 左边是光秃秃的,右边是镜子。您可以清除,镜像的配置文件有fetch键,这意味着您可以更新它,通过git remote updategit fetch --all

$ git clone --bare https://github.com/example

这个命令将使新的"example"目录本身$GIT_DIR(而不是example/.git)。同样,远程的分支头被直接复制到相应的本地分支头,而不需要映射。使用此选项时,既不会创建远程跟踪分支,也不会创建相关配置变量。

$ git clone --mirror https://github.com/example

与裸克隆一样,镜像克隆包括所有远程分支和标记,但所有本地引用(包括远程跟踪分支、注释等)在每次获取时都将被覆盖,因此它将始终与原始存储库相同。

git clone不同,git clone --mirrorgit clone --bare都是裸回购。它们之间的区别在config文件中。

git clone的配置文件如下:

[remote "origin"]
url = https://github.com/example
fetch = +refs/heads/*:refs/remotes/origin/*

git clone --bare的配置文件如下:

[remote "origin"]
url = https://github.com/example

git clone --mirror的配置文件如下:

[remote "origin"]
url = https://github.com/example
fetch = +refs/*:refs/*
mirror = true

因此,我们可以看到主要的区别在于用于获取的refspec

refspec的格式首先是可选的+,然后是 <src>:<dst>,其中<src>是引用 远程端和<dst>是这些引用将被跟踪的地方 本地。+告诉Git更新引用,即使它不是 快进。< / p >

git remote add origin命令自动写入git clone的情况下,Git在服务器上获取refs/heads/下的所有引用,并在本地将它们写入refs/remotes/origin/

对于git clone --bare,没有用于获取的refspec。

对于git clone --mirror,用于获取的refspec看起来像fetch = +refs/*:refs/*。这意味着,tagsremotesreplace(在refs目录下)以及heads也将被获取。注意,默认情况下#EYZ7只获取heads

注1: git clone --mirrorgit clone --bare --mirror是等价的。

注2:packed-refs也有区别。因为它记录的信息与refs/heads/refs/tags/和好友记录的信息相同,以一种更有效的方式记录。