网易首页 > 网易号 > 正文 申请入驻

使用 NFS 将 Git 提交记录显示成文件目录 | Linux 中国

0
分享至


导读:某天,我突发奇想 —— 是否能把 Git 存储库制作成一个 FUSE 文件系统,然后把所有的提交记录做成文件夹呢?

本文字数: 6163,阅读时长大约: 8分钟

大家好!某天,我突发奇想 —— 是否能把 Git 存储库制作成一个 FUSE 文件系统,然后把所有的提交记录做成文件夹呢?答案是肯定的!有 github.com、 belkadan.com 和用于 Plan 9 号的 orib.dev。

但在 Mac 上使用 FUSE 实在很烦人 —— 你需要安装一个内核扩展,但由于安全的原因,Mac OS 上安装内核扩展看起来越来越难了。此外,我还有一些想法,希望能用与这些项目不同的方式来组织文件系统。

因此,我想在 Mac OS 上尝试 FUSE 以外的挂载文件系统的方法会很有趣,因此我创建了一个名为 github.com 的项目来做这个事。它可以同时使用 FUSE 和 NFS(至少在我的电脑上),WebDav 的实现起来还有点问题。

这个项目很有实验性(我不确定这究竟是一个有用的软件,还是一个思考 Git 如何工作的有趣玩具),但写起来很有趣,我自己也很喜欢在小型存储库中使用它,下面是我在写这个项目时遇到的一些问题。

目标:像文件夹一样显示提交记录

我做这个事的主要目的是给大家一些启发:Git 核心是如何运行的。总结来说,Git 提交记录实际上和文件夹非常类似 —— 每个 Git 提交都包含一个目录,其中 jvns.ca,这个目录也可以有子目录,依此类推。

只是为了节省磁盘空间,Git 提交实际上并不是以文件夹的形式实现的。

而在git-commit-folders,所有的提交记录实际上看起来就是一个文件夹,如果你想浏览历史提交记录,你可以像浏览文件系统一样浏览它们!例如如果你像查看我的博客的初始提交记录,你可以如下操作:

  1. $ ls commits/8d/8dc0/8dc0cb0b4b0de3c6f40674198cb2bd44aeee9b86/

  2. README

其他之后的提交记录,如下:

  1. $ ls /tmp/git-homepage/commits/c9/c94e/c94e6f531d02e658d96a3b6255bbf424367765e9/

  2. _config.yml config.rb Rakefile rubypants.rb source

分支是符号链接

通过git-commit-folders挂载的文件系统中,提交是唯一真正的文件夹 —— 其他一切(分支、标签等)都是提交记录的符号链接。这反映了 Git 底层的工作方式。

  1. $ ls -l branches/

  2. lr-xr-xr-x 59 bork bazil-fuse -> ../commits/ff/ff56/ff563b089f9d952cd21ac4d68d8f13c94183dcd8

  3. lr-xr-xr-x 59 bork follow-symlink -> ../commits/7f/7f73/7f73779a8ff79a2a1e21553c6c9cd5d195f33030

  4. lr-xr-xr-x 59 bork go-mod-branch -> ../commits/91/912d/912da3150d9cfa74523b42fae028bbb320b6804f

  5. lr-xr-xr-x 59 bork mac-version -> ../commits/30/3008/30082dcd702b59435f71969cf453828f60753e67

  6. lr-xr-xr-x 59 bork mac-version-debugging -> ../commits/18/18c0/18c0db074ec9b70cb7a28ad9d3f9850082129ce0

  7. lr-xr-xr-x 59 bork main -> ../commits/04/043e/043e90debbeb0fc6b4e28cf8776e874aa5b6e673

  8. $ ls -l tags/

  9. lr-xr-xr-x - bork 31 Dec 1969 test-tag -> ../commits/16/16a3/16a3d776dc163aa8286fb89fde51183ed90c71d0

这个并不能完全呈现 Git 的所有工作机理(相比简单的类似文件夹的提交,还有很多复杂的细节),但是我希望大家对“每个提交如同一个文件夹,里面有你的旧版本代码”有一个直观的认识。

这么做有什么好处呢?

在我深入介绍它的实现之前,我想说下为什么把 Git 提交记录变成拥有文件夹的文件系统很有用。我的很多项目最终都没有真正使用过(比如 github.com),但我发现自己在做这个项目的时候确实使用到了一些。

目前为止我发现主要用处是:

◈ 查找已经删除的函数 - 可以用grep someFunction branch_histories/main/*/commit.go查找它的旧版本

◈ 快速查看其他分支的一个文件并从其拷贝一行,如vim branches/other-branch/go.mod

◈ 在每个分支中搜索某个函数,如grep someFunction branches/*/commit.go

所有这些操作都通过提交记录的符号链接,来替代提交记录的直接引用。

这些都不是最有效的方法(你可以用git showgit log -S或者git grep来完成类似操作),但是对我个人来说,我经常忘记 Git 语法,而浏览文件系统对我来说更简单。git worktree还允许你同时签出多个分支,但对我来说,为了看一个文件而设置整个工作树感觉很奇怪。

接下来我想谈谈我遇到的一些问题。

问题 1: 用 WebDav 还是 NFS?

Mac OS 原生支持的两个文件系统是 WebDav 和 NFS。我说不出那个更新容易实现,所以我就索性尝试两个都支持。

起初,WebDav 的实现看起来更容易一些,在 golang.org 上有一个 pkg.go.dev,这个很好配置。

但这个实现不支持符号链接,我想可能原因是它用的是io/fs接口,而io/fs还不支持 github.com。不过看起来正在进行中。所以我放弃了 WebDav,而决定重点放在 NFS 实现上了,用 github.com NFSv3 的库文件来实现。

有人也提到了 Mac 上的 developer.apple.com,我还没有深入了解这个。

问题 2: 如何确保所有的实现保持一致?

我已经实现了三个不同的文件系统(FUSE、NFS 和 WebDav),但对我来说还是没搞清楚如何避免大量的重复代码。

我的朋友 Dave 建议写一个核心实现,然后写一个适配器(如fuse2nfsfuse2dav)来转换成 NFS 和 WebDav 版本。这个看起来需要我着手实现三个文件系统的接口:

◈ 对应 FUSE 的fs.FS

◈ 对应 NFS 的billy.Filesystem

◈ 对应 WebDav 的webdav.Filesystem

因此我把所有的核心逻辑放到fs.FS接口上,然后写两个函数:

func Fuse2Dav(fs fs.FS) webdav.FileSystem

func Fuse2NFS(fs fs.FS) billy.Filesystem

所有的文件系统都比较类似,因此转换起来不是很难,但就是有大量的烦人的问题需要修复。

问题 3: 我不想罗列所有的提交记录怎么办

一些 Git 存储库有成千上万的提交记录。我的第一个想法是如何让commits/看起来是空的,这样就可以如下展示:

  1. $ ls commits/

  2. $ ls commits/80210c25a86f75440110e4bc280e388b2c098fbd/

  3. fuse fuse2nfs go.mod go.sum main.go README.md

因此所有的提交记录可以直接查看,但是又不能罗列它们。这个对文件系统是一个奇怪的事情,实际上 FUSE 可以做到。但我在 NFS 上无法实现。我认为这里的原因是,如果你告诉 NFS 某个目录是空的,它就会认为该目录实际上是空的,这是合理的。

我们最终是这样处理的:

◈ 按照.git/objects的方式,以前两个字符组织管理提交记录(因此ls commits会显示0b 03 05 06 07 09 1b 1e 3e 4a),但这样做会分为两层,这样18d46e76d7c2eedd8577fae67e3f1d4db25018b0则为commits/18/18df/18d46e76d7c2eedd8577fae67e3f1d4db25018b0

◈ 开始只罗列一次所有的已经打包的提交哈希,将它们缓存在内存中,然后后面仅更新稀疏对象。主要思路是版本库中几乎所有的提交都应该打包,而且 Git 不会经常重新打包提交

这个看起来在拥有百万提交记录的 Linux 内核的 Git 存储库上似乎效果不错。在我的机器上实测它初始化大概需要一分钟,之后只需快速增量更新即可。

每个提交哈希只有 20 个字节,因此缓存 1 百万个提交哈希也不是很大,大约 20MB。

我认为更聪明的做法是延迟加载提交列表 —— Git 会按提交 ID 对其打包文件进行排序,所以你可以很容易地进行二叉树搜索,找到所有以1b1b8c开始的提交。我用的 github.com 对此并不支持,因为罗列出来 Git 存储库所有的提交记录确实一个奇怪的事情。我花了 github.com 尝试实现它,但没有达到我想要的性能,所以就放弃了。

问题 4: 不是目录

我常遇到下面这个错误:

  1. "/tmp/mnt2/commits/59/59167d7d09fd7a1d64aa1d5be73bc484f6621894/": Not a directory (os error 20)

这起初真的把我吓了一跳,但事实证明,这只是表示在列出目录时出现了错误,而 NFS 库处理该错误的方式就是显示 “Not a directory”(不是目录)。这个错误遇到了很多次,我需要每次跟踪这个错误的根源。

有很多类似错误。我也遇到cd: system call interrupted,令人沮丧的是,但最终也只是程序中的其他错误。

我意识到终极大法是用 Wireshark 查看 NFS 发送和接受的数据包,很多问题便可迎刃而解。

问题 5: inode 编号

在开始的时候我不小心将所有的文件夹的 inode 设为 0。这很糟糕,因为如果在每个目录的 inode 都为 0 的目录上运行查找,它就会抱怨文件系统循环并放弃,这个也是符合逻辑的。

我通过定义一个inode(string)来修复这个问题,通过散列字符串来获取 inode 编号,并使用树 ID / blob ID 作为散列字符串。

问题 6: 过期文件句柄

我一直遇到这个“Stale NFS file handle”(过期文件句柄)错误。问题是,我需要获取未知的 64 字节 NFS “文件句柄”,并将其映射到正确的目录。

我使用的 NFS 库的工作方式是为每个文件生成一个文件句柄,并通过固定大小的缓存来缓存这些引用。这对小型存储库来说没问题,但是如果对于拥有海量的文件的存储库来说,由于缓存就会溢出,就会导致“stale file handle” 错误。

这仍然是个问题,我不知道如何解决。我不明白真正的 NFS 服务器是如何做到这一点的,也许它们只是有一个非常大的缓存?

NFS 文件句柄占用 64 个字节(不是比特),确实很大,所以很多时候似乎可以将整个文件路径编码到句柄中,根本不需要缓存。也许我会在某个时候尝试实现这一点。

问题 7: 分支历史

branch_histories/目录目前仅罗列对应分支的最近 100 个提交记录。我不知道该怎么做,如果能以某种方式列出分支的全部历史就更好了。也许我可以使用commits/目录中类似的子文件夹技巧。

问题 8: 子模块

Git 存储库有时包含了子模块。由于目前我对子模块的理解还不深入,我先忽略它吧。因此这个算是一个问题。

问题 9: NFSv4 是否更好?

我构建这个项目使用的是 NFSv3 库,因为我当时只能找到一个 NFSv3 的 Go 库文件。可当我搞完的时候才发现了一个名叫 buildbarn 的项目里有 github.com。有没有可能用它会更好一些?

我不知道这样做有什么问题,或者用 NFSv4 有哪些优点?我还有点不确定是否要使用 buildbarn NFS 库,因为不清楚他们是否希望其他人使用它。

就这些吧

之前已经解决了很多问题我都忘记了,这是我目前能回想起来的。我未来有可能解决或根本解决不了 NFS 的“过期文件句柄” 错误,或者“在 Linux 内核的存储库上启动需要 1 分钟”的问题,就这样吧。

感谢我的朋友 github.com,他给我了很多文件系统方面的帮助。

(题图:DA/d22b1c01-e80a-4529-b88a-419ceef74b5e)

via:

作者: 选题: 译者: 校对:

本文由 原创编译, 荣誉推出

LCTT 译者 :guevaraya

翻译: 12.0 篇

贡献: 1870 天

2018-11-23

2024-01-06

https://linux.cn/lctt/guevaraya

欢迎遵照 CC-BY-SA 协议规定转载,

如需转载,请在文章下留言 “ 转载:公众号名称”,

我们将为您添加白名单,授权“ 转载文章时可以修改”。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
伊朗总统坠机遇难,伊朗对华态度或发生转变,沙伊和解或成泡影

伊朗总统坠机遇难,伊朗对华态度或发生转变,沙伊和解或成泡影

基斯默默
2024-05-21 15:44:37
新东方:教唆46名孩子说谎,赴美被拒签,践踏诚信,别想再来了

新东方:教唆46名孩子说谎,赴美被拒签,践踏诚信,别想再来了

大风文字
2024-05-21 06:44:20
全球最大云计算公司暂停采购英伟达“超级芯片” 原因竟是升级太快

全球最大云计算公司暂停采购英伟达“超级芯片” 原因竟是升级太快

财联社
2024-05-22 00:34:11
799克黄金被制成挎包链条入境被查,网友:神操作

799克黄金被制成挎包链条入境被查,网友:神操作

三月柳
2024-05-20 15:20:54
历史重演..李哥曾因无力偿还3200万失去米兰所有权,结束中资时代

历史重演..李哥曾因无力偿还3200万失去米兰所有权,结束中资时代

直播吧
2024-05-21 11:46:16
NBA本季最佳防守二阵:卡鲁索、霍乐迪、杰登、萨格斯、怀特

NBA本季最佳防守二阵:卡鲁索、霍乐迪、杰登、萨格斯、怀特

懂球帝
2024-05-22 02:31:07
原来森林北也是二婚。还有个女儿

原来森林北也是二婚。还有个女儿

琼瑶史事
2024-05-19 19:01:44
泰国高僧通灵劳荣枝冤魂:与法子英前世是苦命鸳鸯,再轮回需1000年

泰国高僧通灵劳荣枝冤魂:与法子英前世是苦命鸳鸯,再轮回需1000年

古今档案
2024-05-18 11:31:51
禁停“电鸡”,三元里出现了退租潮...

禁停“电鸡”,三元里出现了退租潮...

广州楼市发布
2024-05-21 21:01:51
以太坊狂飙近20%,价格一度超3700美元!比特币突破7.1万美元!港交所现货ETF走强:三只以太币STF涨超19%

以太坊狂飙近20%,价格一度超3700美元!比特币突破7.1万美元!港交所现货ETF走强:三只以太币STF涨超19%

和讯网
2024-05-21 12:22:15
给《我是歌手》十位“候选歌手”实力排个名,孙楠第5,韩红第2

给《我是歌手》十位“候选歌手”实力排个名,孙楠第5,韩红第2

皮皮电影
2024-05-21 09:22:10
美国彻底摊牌了!6国首脑接连遭遇暗杀!

美国彻底摊牌了!6国首脑接连遭遇暗杀!

大国观察眼
2024-05-22 00:41:57
王心刚:泪目!一路好好走!再无国民第一男神,93岁与病妻爱65年

王心刚:泪目!一路好好走!再无国民第一男神,93岁与病妻爱65年

娱乐圈阿榨
2024-05-21 10:34:13
夺冠仅1天,英超冠军遭指控!3种处罚方式曝光:降级+被剥夺奖杯

夺冠仅1天,英超冠军遭指控!3种处罚方式曝光:降级+被剥夺奖杯

侃球熊弟
2024-05-20 21:00:28
历史首人!文班亚马新秀赛季入选最佳防守一阵

历史首人!文班亚马新秀赛季入选最佳防守一阵

直播吧
2024-05-22 02:18:13
博主声称小米派人堵家门口,不删微博就折腾他父母

博主声称小米派人堵家门口,不删微博就折腾他父母

映射生活的身影
2024-05-21 13:18:19
中俄天然气管道,非绕道哈萨克斯坦,中国一步妙棋,给了普京大礼

中俄天然气管道,非绕道哈萨克斯坦,中国一步妙棋,给了普京大礼

吕喆有话说
2024-05-21 08:53:20
安徽画家关玉梅被执行死刑前,拒绝吃断头饭,行刑时已四肢瘫软

安徽画家关玉梅被执行死刑前,拒绝吃断头饭,行刑时已四肢瘫软

一个人讲故事
2024-05-05 21:46:11
汪峰官宣恋情,章子怡、葛荟婕赢麻了!小苹果力挺宇宙超可爱妈妈

汪峰官宣恋情,章子怡、葛荟婕赢麻了!小苹果力挺宇宙超可爱妈妈

旧梦影看世界
2024-05-21 14:23:25
黄奇帆:海南不可能超过香港,因为香港有10条致胜法宝无人超越!

黄奇帆:海南不可能超过香港,因为香港有10条致胜法宝无人超越!

蓝色海边
2024-05-21 18:43:36
2024-05-22 03:46:44
Linux
Linux
Linux 中国开源社区
8016文章数 73123关注度
往期回顾 全部

科技要闻

小鹏一季度营收65.5亿,经营亏损16.5亿

头条要闻

美媒:莱希之死基本为小哈梅内伊接替父亲职位铺平道路

头条要闻

美媒:莱希之死基本为小哈梅内伊接替父亲职位铺平道路

体育要闻

兄弟们,为了我,拿下冠军吧!

娱乐要闻

杨洋乔欣聊天记录曝光!还牵扯张天爱

财经要闻

中植系的销售,不退40亿被抓了

汽车要闻

四排八座纯电MPV/续航超过800km 翼真L380开启预订

态度原创

时尚
家居
艺术
健康
亲子

今年夏天最流行的颜色居然是它?

家居要闻

生活蜕变 简约理念雕刻理想居所

艺术要闻

挖掘艺术界未来的璀璨星辰 | 莱俪青年艺术奖获奖艺术家邓启鹏

在中国,到底哪些人在吃“伟哥”?

亲子要闻

坐月子这件事很重要,所以十多年,她一直为此操劳

无障碍浏览 进入关怀版