243

我一直在阅读 Git 中的裸机和非裸机/默认存储库。我一直无法很好地理解(理论上)它们之间的差异,以及为什么我应该“推送”到一个裸存储库。这是交易:

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

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

那么,我为什么要使用裸存储库,为什么不呢?有什么实际区别?我想,这对更多从事项目工作的人没有好处。

你对这种工作有什么方法?建议?

4

11 回答 11

109

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

~/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

远程的分支头也直接复制到相应的本地分支头,而不将它们映射到 refs/remotes/origin/。使用此选项时,既不会创建远程跟踪分支,也不会创建相关的配置变量。

据推测,当它创建一个裸存储库时,Git 假设该裸存储库将作为多个远程用户的源存储库,因此它不会创建默认的远程源。这意味着基本git pullgit push操作将不起作用,因为 Git 假定没有工作区,您不打算对裸存储库提交任何更改:

~/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$ 
于 2011-04-04T17:11:22.420 回答
78

5年太晚了,我知道,但实际上没有人回答这个问题:

那么,我为什么要使用裸存储库,为什么不呢?有什么实际区别?我想,这对更多从事项目工作的人没有好处。

你对这种工作有什么方法?建议?

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

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

于 2017-03-20T10:04:47.977 回答
77

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

Git 命令git clonegit init两者都有在--bare没有初始工作区的情况下创建存储库的选项。不幸的是,Git 将工作空间和存储库这两个独立但相关的概念混为一谈,然后使用令人困惑的术语“”来区分这两个概念。

于 2011-04-04T19:23:00.043 回答
74

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

  • 在远程服务器上使用裸存储库以允许多个贡献者推送他们的工作。
  • Non-bare - 具有工作树的那个在项目的每个贡献者的本地机器上是有意义的。
于 2015-02-10T09:58:27.473 回答
25

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

  1. 存储库中所有文件的快照(这就是 Git 术语中“工作树”的意思)
  2. 对存储库中所有文件所做的所有更改的历史记录(似乎没有包含所有这些的简洁的 Git 行话)

快照就是您可能认为的项目:您的代码文件、构建文件、帮助脚本以及您使用 Git 进行版本控制的任何其他内容。

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

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

裸仓库是没有快照的 Git 仓库。它只存储历史。

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

如果您想更深入地解释裸存储库和另一个示例用例,我在这里写了一篇博文:https ://stegosaurusdormant.com/bare-git-repo/

于 2019-10-27T21:35:35.027 回答
21

非裸存储库仅具有已签出的工作树。工作树不存储关于存储库状态的任何信息(分支、标签等);相反,工作树只是 repo 中实际文件的表示,它允许您处理(编辑等)文件。

于 2011-04-04T15:41:04.140 回答
19

裸存储库有以下好处

  • 减少磁盘使用
  • 与远程推送相关的问题更少(因为没有工作树不同步或有冲突的更改)
于 2011-04-04T15:48:38.263 回答
14

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

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

于 2015-06-02T09:24:08.920 回答
11

我当然不是 Git “专家”。我使用 TortoiseGit 已经有一段时间了,当它问我是否想在创建一个“裸”repo 时想知道它在说什么。我正在阅读本教程: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 等远程存储/分发存储库是创建“裸”存储库的示例。如果您要建立自己的类似“共享中心”,您会自己制作一个。

于 2015-08-11T14:21:11.490 回答
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/
于 2018-04-03T09:52:09.403 回答
2

$ git help repository-layout

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

  • 工作树根目录下的 .git 目录;
  • 一个 .git 目录,它是一个存储库(即没有自己的工作树),通常用于通过推入并从中获取来与他人交换历史记录。
于 2018-12-02T16:28:01.053 回答