git fork 一个 200M 的仓库 A ,得到 B ,我在 B 的裸库查看大小 du -sh ,可以看到是 200M ,但是我整个磁盘的大小并不会增加 200M ,机会没变化。这是 git 的什么机制做到的呢?假如我把 B copy 到/tmp/B ,那磁盘就增加了 200M ,又是什么原理?肯定跟底层的文件引用啥的有关系,但是我在 B 的裸库中并没有见到软链接

没见到软链接,那硬链接呢

git 有 fork 这个命令吗…

git 的原理没了解过吗?

#3 git 有 fork 这玩意儿么,还原理所以楼主你具体是怎么操作的

op 在服务器建了个 git 服务(可以理解成 gitlab ),然后在 gitlab 里进行 fork 操作,fork 了一个很大的仓库,但 git 服务占用的服务器磁盘空间没有增加很多,这都看不明白吗而这个现象和 git 在本地的存储原理是息息相关的

什么本地存储原理,本质上来说不就是一堆 blob 和 pack 对象么,这怎么解释 OP 的问题:空间没有增长? git 本身就没有 fork 这玩意儿,他规定了服务端是实现 fork 是复制一个新的目录还是软硬链接实现 fork 么,规定了 fork 的时候是否执行一次 aggressive gc 么?规定了服务端是否使用去重文件系统么?你要是能回答就回答,不会回答就别嚷嚷着:你不懂“git 在本地的存储原理”

#6 一堆 blob 和 pack 对象还不够解释吗?

那你解释一下?快解释,为什么 fork 了一个空间没有增长

#6 一堆 blob 和 pack 对象还不够解释吗?你干脆从 CPU 是怎么从沙子造出来开始解释好了

你干脆从因为这样所以这样来回答所有问题好了

#8 fork 了又没增加新 blob 和 pack ,为啥会增长,为啥不能解释

你 fork 的仓库和别人的仓库放在 path 么? git 规定了么? gitlab (假设是 gitlab )用的不是复制而是软硬链接么?还是用的去重文件系统?

#12 fork 行为不增加 blob 和 pack ,基于此原理就能实现一个 fork 不增加存储占用的 git 服务,还有啥不够吗?你再往下深究什么软硬链接去重文件系统这个系统背后的细节具体是怎么设计的,不就是我之前说的干脆从 CPU 是怎么从沙子造出来开始解释好了说得好像软硬链接文件去重我就不能继续往下深究一样,你咋不再往下解释解释软硬链接文件去重怎么就能节省存储空间了,为啥存储数据会增加存储空间,为啥磁盘会用容量上限,为啥磁盘能存储数据

“基于此原理就能实现一个 fork 不增加存储占用的 git 服务”你这个回答就是假设了 OP 用的是一个能能够做到重复文件不增加存储空间的 git 托管实现或者服务器了

#14 服务器存 blob 和 pack 就行了,都不需要去重

不管是 blob 还是 pack ,还是小猫小狗存,结果都是一样的,答案就是:服务器存小猫小狗就行了并且为什么假定服务器在复制一个仓库之后不对仓库进行 gc 呢,存 blob 和 pack 如果遇到 hash 冲突呢( git 的 hash 冲突是存在的并且很坑的),这都是很复杂的情况,这其实和 git 的实现没什么关系,这完全是 git 服务的实现有关

#16 你说的这些不还是我最开始说的问题「干脆从 CPU 是怎么从沙子造出来开始解释好了」hash 冲突这些不还是实现细节,而且还是 blob 、pack 实现的(必须处理的) edge case ,fork 一个仓库服务端存储没有大幅度增加,到底是因为 blob 、pack 的设计呢?还是因为你说的这些 edge case 呢?而且为啥你会假定 fork 一个仓库就非得把所有东西复制一遍再 gc ,不是很能理解blob 、pack 的设计不就是 git 的基本原理的一部分吗?所以我说让 OP 去了解 git 的原理到底有什么问题? fork 后服务端存储没有大幅度增加,blob 、pack 的设计就是最最最最主要的原因

即使不是 blob 和 pack 存,是用小猫小狗存,只要他要在磁盘上存东西,结果都是一样,所以这个问题的本质和 git 的原理没什么关系,而是服务器的实现

而我们没法假定 OP 的服务用的是什么,在 OP 给出更多信息之前,也不知道问题的答案

#18 我十分怀疑你还是没明白 OP 问的问题是什么,OP 是在服务器建了个 git server ( gitlab 这种),而不是在服务器 git clone 了一个仓库然后又复制了一份什么叫「即使不是 blob 和 pack 存」,git 底层那些东西不就是 blob 、pack ,不存这些存什么,fork 一个仓库没增加 blob 、pack ,自然存储占用不会大幅增加

我理解 OP 的问题和你的每一条回复,但你没明白我的观点:导致这个现象的原因根本不是 git 的底层实现,而是 git 服务( gitlab GitHub or 自建的其他任何一种 git 托管服务)的服务实现,你所说的 edge case ,gc 等不重要更加应证了这一点:这不是 git 管的事情,不是 git 的底层原理,这是服务的事

#21 难道你想要 git server 完全抛弃 blob 、pack 这些原生概念,设计一个不包含 blob 、pack 概念的存储系统?你也是有点离谱但凡 git server 基于 blob 、pack 去进行存储,blob 和 pack 都没增加,我为啥还要考虑 git server 是怎么存储 blob 、pack 的,最重要的去重你说是在 blob 、pack 这个抽象层发生的还是在存储层发生的?除非你去设计一个命名存储的东西每增加,存储占用仍会大量增加的存储系统

首先:"但凡 git server 基于 blob 、pack 去进行存储", 你这已经是在假设 git 服务的实现了其次:我为什么不能直接使用 path 进行存储,非得用 blob ,pack 存储,将仓库所在 path 里的所有文件都存储在一个去重的文件系统/第三方存储服务里,不就实现了这个功能了么,并且抽象层次更好,不用记录 blob 、pack 和仓库的关系,直接目录作为仓库,和原生的 git 概念完全一致最后:我这里不是在讨论什么样的服务设计更好,而是证明,问题讨论到这个范畴,已经不是 git 的问题了,而是 git 服务怎样实现才导致了这个情况,git 本身是保证不了复制( fork )一个仓库不增加存储空间的

#23 「为什么不能直接使用 path 进行存储,非得用 blob ,pack 存储」是真离谱,blob 、pack 本来就是底层的东西,你说你不用这些底层的概念去存储,要把底层的这些东西揉碎了再重新设计一套系统去存,真是离谱他妈给离谱开门

打起来了。。。。

path 为什么是打散的,目录是 path ,文件也是 path ,用 path 存就是直接简单直观的,甚至直接加一个 bucket://prefix 就可以同步到任何一个文件存储系统,加一个本地路径前缀就是本地文件系统,你自己电脑上 git 仓库不就是存在一个 path 么

/go/flamewar笑死,这也能打起来

不是打起来了,对任意技术一个问题,知道答案就回答,不知道就说不知道,不瞎猜,问题有误有不充分的就提出疑问,说一句“XXX 的原理没了解过么”,让别人猜谜语去吧,你看吵了半天,OP 的问题答案,还是不知道具体原因,在 OP 出来给出自己的配置之前,谁也答不上来真实具体的原因

#26 你对一个 git 仓库的理解就是当前 HEAD 表面的那些文件吗?所有的历史提交的所有版本的文件你不管?同一个 path 下可能有 100 个版本的文件

一个 git 的仓库,不管是裸仓库还是普通仓库,PATH 不包含你说的那些 blob pack 等等等等文件么?

各位,我来说一句