裸仓库和非裸仓库之间的实用区别是什么?


213

我一直在阅读有关Git中裸机和非裸机/默认存储库的信息。从理论上讲,我还不太了解它们之间的区别,以及为什么我应该“推送”到一个裸仓库。这是交易:

目前,我是唯一在3台不同计算机上从事项目工作的人,但是以后会有更多人参与其中,因此我将Git用于版本控制。我在所有计算机上克隆了裸仓库,当我在其中一台计算机上完成修改时,我提交并将更改推送到裸仓库。根据我的阅读,裸存储库没有“工作树”,因此,如果克隆裸仓库,则不会有“工作树”。

我猜工作树存储了项目中的提交信息,分支等。那不会出现在裸仓库中。因此,对我来说,使用工作树将“提交”提交“回购”似乎更好。

那么,为什么我应该使用裸存储库,为什么不使用?实际区别是什么?我想这对更多的人从事一个项目没有好处。

您从事这种工作的方法是什么?有什么建议吗?


4
AeroCross,您可以克隆一个裸存储库以创建一个非裸存储库(即具有工作区的存储库)。因此,使用git clone可以在裸仓库和非裸仓库之间自由转换。
Derek Mahar

13
@AeroCross:这与转换无关;无关紧要的是另一端。如果运行git clone --bare,将得到裸仓库,如果运行git clone,将得到非裸仓库。您曾经克隆过的每个公共项目(例如托管在github上)在另一端都是裸仓库。
卡斯卡贝尔2011年

1
Jefromi,我正在纠正AeroCross的观点,“因此,如果克隆裸仓库,我将没有“工作树””,因此这是一种转换。并非每个公共项目都必须是裸仓库。这只是一个典型的选择,因为光秃的存储库由于没有工作树而更加节省空间(不过,它与没有工作树的任何存储库一样具有空间效率)。
德里克·马哈尔

2
@Derek:但关键是,一旦找到.git目录,则获取操作完全不知道远程是否裸露。它不会转换。它只是从远程获取所需的内容,然后将其放置在应有的位置。没有什么可以转换的。这就是我要向OP强调的内容。而且我很清楚公共项目并不一定要光秃秃的,但是因为人们并不愚蠢,所以他们基本上都是愚蠢的。我想我做了一个可以接受的概括。
卡斯卡贝尔2011年

2
请参阅推送到非裸存储库,它提供了对裸存储库用法的另一个很好的解释。
Craig McQueen 2014年

Answers:


95

裸存储库和非裸存储库之间的另一个区别是,裸存储库没有默认的远程原始存储库:

~/Projects$ git clone --bare test bare
Initialized empty Git repository in /home/derek/Projects/bare/
~/Projects$ cd bare
~/Projects/bare$ git branch -a
* master
~/Projects/bare$ cd ..
~/Projects$ git clone test non-bare
Initialized empty Git repository in /home/derek/Projects/non-bare/.git/
~/Projects$ cd non-bare
~/Projects/non-bare$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

从手册页git clone --bare

同样,将远程站点的分支头直接复制到相应的本地分支头,而无需将其映射到ref / remotes / origin /。使用此选项时,不会创建远程跟踪分支或相关的配置变量。

大概在创建裸存储库时,Git假定裸存储库将充当多个远程用户的原始存储库,因此它不会创建默认的远程原始存储库。这意味着,由于Git假定没有工作空间,因此您不打算将任何更改提交到裸存储库,因此基本操作git pullgit push操作将不起作用:

~/Projects/bare$ git push
fatal: No destination configured to push to.
~/Projects/bare$ git pull
fatal: /usr/lib/git-core/git-pull cannot be used without a working tree.
~/Projects/bare$ 

1
是的,我同意这可以说是裸Git和非裸Git存储库之间最大的区别。非裸存储库具有工作空间,而裸存储库则不是重要的区别,但是git clone --no-checkout也可以创建没有工作空间文件的非裸存储库。
德里克·马哈尔

10
非裸仓库也不一定具有默认的远程“来源”。
mipadi

2
您可以使用轻松创建一个Git存储库git init,这将创建一个没有指定远程的非裸仓库。
mipadi

1
mipadi,的确如此,但这也不是克隆。
德里克·马哈尔

1
这是不正确的。如果已经clone编辑过,则存储库将具有默认来源。如果已在init本地编辑,则不会有这样的来源。这与是否裸露无关。
Noufal Ibrahim 2011年

62

裸Git和非裸Git存储库之间的区分是人为的并且具有误导性,因为工作空间不是存储库的一部分,并且存储库不需要工作空间。严格来说,Git存储库包括描述存储库状态的那些对象。这些对象可以存在于任何目录中,但通常存在于.git工作空间的顶级目录中的目录中。工作空间是一个目录树,代表存储库中的特定提交,但是它可以存在于任何目录中或根本不存在。环境变量$GIT_DIR将工作空间链接到其起源的存储库。

Git命令git clonegit init两者都具有--bare在没有初始工作空间的情况下创建存储库的选项。不幸的是,Git将工作空间和存储库这两个相互独立但又相关的概念融合在一起,然后使用裸露的术语来混淆这两个概念。


61

裸存储库不过是.git文件夹本身,也就是说,裸存储库的内容与本地工作存储库内的.git文件夹的内容相同。

  • 在远程服务器上使用裸仓库,以允许多个贡献者推动其工作。
  • 裸机-具有工作树的树在您项目的每个贡献者的本地计算机上都很有意义。

60

我知道已经晚了5年,但没有人真正回答这个问题:

那么,为什么我应该使用裸存储库,为什么不使用?实际区别是什么?我想这对更多的人从事一个项目没有好处。

您从事这种工作的方法是什么?有什么建议吗?

要直接引用Loeliger / MCullough的书(978-1-449-31638-9,p196 / 7):

裸仓库似乎没什么用,但是它的作用至关重要:充当协作开发的权威焦点。其他开发人员clone以及fetch裸存储库及其push更新...如果您设置了一个供开发人员push更改的存储库,则它应该是裸存储的。实际上,这是更一般的最佳实践的特例,即最佳的实践是发布的存储库应为空。


19

一个非裸仓库仅包含一个已签出的工作树。工作树不存储有关存储库状态的任何信息(分支,标签等);相反,工作树只是存储库中实际文件的一种表示形式,它使您可以处理(编辑等)文件。


因此,这意味着我可以将分支,标签等添加到裸仓库,然后从裸仓库拉到非裸仓库/生产仓库?
AeroCross 2011年

2
mipadi(非裸仓库)可能没有检出的树。如果您使用创建非裸露的存储库,就会出现这种情况git clone --no-checkout。在这种情况下,非裸仓库具有工作空间的位置,但是Git不会将任何文件签出到该工作空间中。
德里克·马哈尔

17

裸仓库在以下方面有好处

  • 减少磁盘使用
  • 与远程推送有关的问题更少(因为那里没有工作树不同步或有冲突的更改)

3
因此,裸仓库是与无法访问THEIR仓库的几个人一起工作的最佳/推荐方式吗?(像SVN那样的Kinda吗?)
AeroCross 2011年

2
AeroCross,我想说一个裸仓库是那种情况的不错选择。
Derek Mahar

12

非裸仓库允许您通过创建新的提交(进入工作树)来捕获更改。

仅通过传输其他存储库中的更改来更改裸存储库。


10

我当然不是Git的“专家”。我使用TortoiseGit已有一段时间了,当它问我是否要创建一个“裸”存储库时,我想知道它在说什么。我正在阅读本教程:https : //www.atlassian.com/git/tutorials/setting-up-a-repository/git-init,它解决了这个问题,但是我仍然不太理解这个概念。这对我们有很大帮助:http : //bitflop.com/tutorials/git-bare-vs-non-bare-repositories.html。现在,第一个也是有道理的!

根据这些消息来源,简而言之,在要设置分发点的服务器上使用“裸”存储库。它不打算在您的本地计算机上使用。通常,您将提交从本地计算机推送到远程服务器上的裸存储库,并且您和/或其他人将提交从裸存储库拉到本地计算机。因此,您的GitHub,Assembla等远程存储/分发存储库就是创建“裸机”存储库的示例。如果您要建立自己的类似“共享中心”,您将自己做一个。


ooooh,现在我明白了
Fuseteam

9

默认/非裸Git存储库包含两种状态:

  1. 一个快照的所有文件的存储库中的(这是Git的行话是什么“工作树”的意思)
  2. 对存储库中曾经存在的所有文件进行的所有更改的历史记录(似乎没有一个简洁的Git术语涵盖了所有这些内容)

快照是什么,你可能认为的项目:你的代码文件,生成文件,辅助脚本和其他任何你的版本使用Git。

历史上是允许你检查出不同的提交,并得到一个什么在你的仓库中的文件看犯下加入时像一个完整的快照状态。它由Git内部的一堆数据结构组成,您可能从未直接进行过交互。重要的是,历史记录不仅存储元数据(例如“用户U在时间T作为提交C的一部分将这许多行添加到文件F”),还存储数据(例如“用户U将这些确切的行添加到文件F” )。

裸存储库的关键思想是您实际上不需要快照。Git保留快照,因为它对于希望与您的代码进行交互的人类和其他非Git进程很方便,但是快照只是复制历史记录中已存在的状态。

一个纯仓库是不具有快照的Git仓库。它只是存储历史记录。

你为什么要这个?好吧,如果仅使用Git与文件进行交互(也就是说,您将不直接编辑文件或使用它们来构建可执行文件),则可以通过不保留快照来节省空间。特别是,如果您要在某处的服务器上维护集中版本的存储库(即,您基本上是托管自己的GitHub),则该服务器可能应该有裸存储库(您仍将在您的裸存储库上使用非裸存储库)不过是本地计算机,因为您可能想编辑快照)。

如果您想对裸仓库和另一个示例用例进行更深入的说明,我在这里写了一篇博客文章:https : //stegosaurusdormant.com/bare-git-repo/


4

这不是一个新的答案,但它帮助我理解了以上答案的不同方面(对于评论来说太多了)。

使用Git Bash只需尝试:

me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../

me@pc MINGW64 /c/Test
$ git init
Initialized empty Git repository in C:/Test/.git/

me@pc MINGW64 /c/Test (master)
$ ls -al
total 20
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 .git/

me@pc MINGW64 /c/Test (master)
$ cd .git

me@pc MINGW64 /c/Test/.git (GIT_DIR!)
$ ls -al
total 15
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 ../
-rw-r--r-- 1 myid 1049089 130 Apr  1 11:35 config
-rw-r--r-- 1 myid 1049089  73 Apr  1 11:35 description
-rw-r--r-- 1 myid 1049089  23 Apr  1 11:35 HEAD
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 hooks/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 info/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 objects/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 refs/

git --bare:相同

me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:36 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../

me@pc MINGW64 /c/Test
$ git init --bare
Initialized empty Git repository in C:/Test/

me@pc MINGW64 /c/Test (BARE:master)
$ ls -al
total 23
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 ./
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:11 ../
-rw-r--r-- 1 myid 1049089 104 Apr  1 11:36 config
-rw-r--r-- 1 myid 1049089  73 Apr  1 11:36 description
-rw-r--r-- 1 myid 1049089  23 Apr  1 11:36 HEAD
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 hooks/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 info/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 objects/

2

$ git help repository-layout

Git存储库具有两种不同的风格:

  • 工作树根目录下的.git目录;
  • .git目录是一个仓库(即没有其自己的工作树),通常用于通过推入该目录并从中取回来与他人交换历史记录。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.