git fork 200M 的仓库,服务端磁盘占用并不会变大,是怎么做到的

266 天前
 weishao666

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

2813 次点击
所在节点    git
47 条回复
cc666
265 天前
@mxT52CRuqR6o5 我理解 OP 的问题和你的每一条回复,但你没明白我的观点:导致这个现象的原因根本不是 git 的底层实现,而是 git 服务( gitlab GitHub or 自建的其他任何一种 git 托管服务)的服务实现,你所说的 edge case ,gc 等不重要更加应证了这一点:这不是 git 管的事情,不是 git 的底层原理,这是服务的事
mxT52CRuqR6o5
265 天前
@cc666 #21 难道你想要 git server 完全抛弃 blob 、pack 这些原生概念,设计一个不包含 blob 、pack 概念的存储系统?你也是有点离谱
但凡 git server 基于 blob 、pack 去进行存储,blob 和 pack 都没增加,我为啥还要考虑 git server 是怎么存储 blob 、pack 的,最重要的去重你说是在 blob 、pack 这个抽象层发生的还是在存储层发生的?除非你去设计一个命名存储的东西每增加,存储占用仍会大量增加的存储系统
cc666
265 天前
@mxT52CRuqR6o5
首先:"但凡 git server 基于 blob 、pack 去进行存储", 你这已经是在假设 git 服务的实现了
其次:我为什么不能直接使用 path 进行存储,非得用 blob ,pack 存储,将仓库所在 path 里的所有文件都存储在一个去重的文件系统/第三方存储服务里,不就实现了这个功能了么,并且抽象层次更好,不用记录 blob 、pack 和仓库的关系,直接目录作为仓库,和原生的 git 概念完全一致
最后:我这里不是在讨论什么样的服务设计更好,而是证明,问题讨论到这个范畴,已经不是 git 的问题了,而是 git 服务怎样实现才导致了这个情况,git 本身是保证不了复制( fork )一个仓库不增加存储空间的
mxT52CRuqR6o5
265 天前
@cc666 #23
「为什么不能直接使用 path 进行存储,非得用 blob ,pack 存储」是真离谱,blob 、pack 本来就是底层的东西,你说你不用这些底层的概念去存储,要把底层的这些东西揉碎了再重新设计一套系统去存,真是离谱他妈给离谱开门
c3de3f21
265 天前
打起来了。。。。
cc666
265 天前
@mxT52CRuqR6o5
path 为什么是打散的,目录是 path ,文件也是 path ,用 path 存就是直接简单直观的,甚至直接加一个 bucket://prefix 就可以同步到任何一个文件存储系统,加一个本地路径前缀就是本地文件系统,你自己电脑上 git 仓库不就是存在一个 path 么
deorth
265 天前
/go/flamewar
笑死,这也能打起来
cc666
265 天前
@c3de3f21 不是打起来了,对任意技术一个问题,知道答案就回答,不知道就说不知道,不瞎猜,问题有误有不充分的就提出疑问,说一句“XXX 的原理没了解过么”,让别人猜谜语去吧,你看吵了半天,OP 的问题答案,还是不知道具体原因,在 OP 出来给出自己的配置之前,谁也答不上来真实具体的原因
mxT52CRuqR6o5
265 天前
@cc666 #26 你对一个 git 仓库的理解就是当前 HEAD 表面的那些文件吗?所有的历史提交的所有版本的文件你不管?同一个 path 下可能有 100 个版本的文件
cc666
265 天前
@mxT52CRuqR6o5 一个 git 的仓库,不管是裸仓库还是普通仓库,PATH 不包含你说的那些 blob pack 等等等等文件么?
root71370
265 天前
各位,我来说一句
atuocn
265 天前
@mxT52CRuqR6o5 @cc666

这问题不能怪 cc666 一直追问。git 没有 fork 命令,所谓 fork 是 gitlab, github 等仓库管理系统的功能。fork 后是 2 个独立仓库,否则你的提交历史、分支、Tag 岂不是混在一起了。那么 2 个独立的 git 仓库,各自有自己的的 blob, pack 一堆巴拉巴拉的东西了。git 本身机制是无法解释一个仓库目录复制一份后,server 的空间没有增长多少。我搭建的 gitlab ,里面的仓库 fork 了许多次,在我担心磁盘空间的时候,我发现这个现象后也很惊讶。但我没有仔细深究,大约猜测是 gitlab 在 fork 仓库的时候,使用硬连接,而不是把相同的文件再复制一份。
darklinden
265 天前
lisxour
265 天前
这一波我只能说 OP 问的问题很有问题,git 并没有 fork 功能,所以你这么一描述,我这个 git 专业户都被你描述得一愣一愣的
weishao666
265 天前
@Muniesa 是的,就是硬链接
Corybyte
264 天前
v2 的技术氛围真浓厚
ysc3839
264 天前
@atuocn git 本身没有 fork 功能,其他第三方 git 管理软件实现 fork 一般是类似共用仓库新建 branch 的做法,commit 是会混在一起的。

比如我最近在 GitHub 上 fork 一个仓库后的 commit ,在原仓库下也是能访问到的
https://github.com/zhongyang219/TrafficMonitor/commit/717d3afbbb836986b7f0abea8de18d87c8f3a4d5
atuocn
264 天前
@ysc3839 github 上建立 fork 的时候,上面会提示:“A fork is a copy of a repository. Forking a repository allows you to freely experiment with changes without affecting the original project. ”
atuocn
264 天前
从实际使用来看,也没有发现两个仓库共用了存储的迹象。你那个提示,我觉得更像是 github 在查询 commits 时,兼顾查询了其他 fork 的仓库后,对你的一个友好提示。op 已经回复,是使用硬链接进行的复制,他应该是查过自己用的 git 管理系统的存储吧。
ysc3839
263 天前
@atuocn 首先面向普通用户的说明文本并不能代表底层架构如何。
其次从实际来看,“git 仓库”可以看成只包含 tag 和 branch ,底层的 object 可以认为和仓库无关,那 fork 后确实不会影响源仓库的 tag 和 branch 。
从另一个角度看,GitHub 也没必要“在查询 commits 时,兼顾查询了其他 fork 的仓库”,因为现在查看这类 commit 时,会加上一个警告“This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.”,以前是出现过利用这种机制去骗人的。
最后 OP 的回复只是猜测。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1019568

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX