裸库和非裸库之间的-实际-区别是什么?

我一直在阅读Git中的裸库和非裸库/默认库。我还不能很好地(从理论上)理解它们之间的区别,以及为什么我应该“推”;到一个裸存储库。事情是这样的:

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

我猜工作树存储了来自项目的提交信息、分支等。这不会出现在裸回购中。所以对我来说,“推”似乎更好。使用工作树提交到回购。

我想,这对更多的人在一个项目上工作没有好处。

你做这种工作的方法是什么?建议吗?

126393 次浏览

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

裸存储库的好处在于

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

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

~/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/。当 这两个选项都没有使用 远程跟踪分支机构也没有 相关配置变量为 创建。< / p >

假设,在创建裸存储库时,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$

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

Git命令git clonegit init都有选项--bare,可以创建没有初始工作区的存储库。不幸的是,Git将工作空间和存储库这两个独立但相关的概念合并在一起,然后使用令人困惑的术语裸露的来区分这两个概念。

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

  • 在远程服务器上使用裸存储库允许多个贡献者推送他们的工作。
  • Non-bare——在项目的每个贡献者的本地机器上有工作树的那个。

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

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

我当然不是一个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。第一个也说得通!

根据这些资料,简而言之,“裸”;Repo用于您想要设置分发点的服务器上。它不适合在本地机器上使用。您通常将提交从本地机器推到远程服务器上的裸回购,然后您和/或其他人从该裸回购拉到您的本地机器。所以你的GitHub, Assembla等远程存储/分发回购是一个例子,其中"bare"创建Repo。如果你要建立一个类似的“分享中心”,你自己也会做一个。

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

那么,为什么我应该使用裸库,为什么不呢?是什么 实际的区别吗?这对更多人没有好处

你做这种工作的方法是什么?建议吗?

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

裸库可能看起来没什么用处,但它的作用是 至关重要的是:作为合作的权威焦点 发展。其他开发人员clonefetch从裸 push更新到它…如果你建立了一个存储库 开发人员push改变,它应该是裸露的。实际上,这是 一种特殊情况下比较普遍的最佳实践,即一种已出版的最佳实践

.仓库应该是空的

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

使用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/

$ git help repository-layout

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

  • 在工作树的根目录下有一个.git目录;
  • 一个.git目录,它是一个裸露的存储库(即没有自己的工作树),通常用于通过推入和从中获取与他人交换历史。

默认/非裸的Git repo包含两段状态:

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

快照就是你可能想到的项目:你的代码文件,构建文件,帮助脚本,以及任何你用Git进行版本的东西。

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

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

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

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

如果你想要更深入地解释裸回购和另一个示例用例,我写了一篇博客文章:https://stegosaurusdormant.com/bare-git-repo/