Given the advent of LLMs and agentic coding, I believe this article needs re-visiting as it makes it much more discoverable to compare individual files across commits.
The two filesystems I could that were natively supported by Mac OS were WebDav and NFS. I couldn’t tell which would be easier to implement so I just tried both”
> None of these are the most efficient way to do this (you can use git show and git log -S or maybe git grep to accomplish something similar), but personally I always forget the syntax and navigating a filesystem feels easier to me.
i feel like some of the old-school commands will benefit from long args, e.g., '--search'. at the time of writing, the current `git log` documentation[1]'s `-S' has _one_ instance of the word 'search'.
(un)related to the article, author went on to contribute documentation updates to git, which were much needed [2]
-S does not mean “search” tho, it means specifically searching the change history for the symbol being added or removed (but not moved, the number of occurrences has to vary). -G includes the symbol being moved (it will flag commits which both remove and add an occurrence).
“git grep” is the correct tool for Julia’s grep, however as usual it has the worst defaults: the work tree (so it’s just a slightly better “grep”), you need to give it a list of revisions to search to get a history search (so usually you pipe-xargs a rev-list into it).
Nice idea. But when taking commits as folders one should delete, add and remame files in the folder and that is not possible in a commit because it creates another commit.
So I think this is nit the right mental model
I loved the views, you could actually have snapshots git style, and best of all binary caches for distributed compilation of C and C++, something that is still not widely deployed.
Oh man. I was just reminded of ClearCase and Perforce and sort of threw up a little in the back of my mouth. You young whipper-snappers who didn't have to use ClearCase and have only used hg or git don't know how bad it could be. When ClearCase was properly configured, it was fine. But having used it at IBM, DSCCC and Bell Canada, only IBM managed it properly. At DSCCC, we had 40 Sun workstations on a single thin-net segment, each of them trying to mount an NFS share from ClearCase. You had to get there at 6AM to be one of the first five people to log in because if you didn't it was unlikely you COULD even log in. I kept a copy of the part of the code I was working with on a tape and would go into the lab and restore it from tape, do some work, then back it up to tape at the end of the day (the lab machines were reformatted at midnight every day.)
But... yes... this is just using NFS locally to see what's already in GIT, which is perfectly find and as Julia says, allows you to appreciate the structure of the git repo. Ignore this old man yelling at clouds.
ClearCase was the main system at Altitude Software in Portugal, and at Nokia, eventually replaced by Subversion.
Yes, it was, is, quite complex and requires a dedicated team, however there are plenty of features that are still to be made available as easyly.
I loved my view configurations, there were some tricks we could do for mix and match what code to see, and the build caches to this day is still not as integrated as sharing object and library files was back then.
GE moved off Clearcase in 2019 because even IBM didn’t want to use or support it anymore. Wasn’t set up as bad as you had but wouldn’t describe it as pleasant. Lot of alias cheatsheets. Now we’re on perforce transitioning to git.
> I fixed this by defining an inode(string) function which hashed a string to get the inode number, and using the tree ID / blob ID as the string to hash.
The tree/blob ID is already a hash though. You don't need to hash it again. Just use the first 8 bytes of the tree ID as the inode.
A couple other people mentioned ClearCase which has something similar if you use their NFS based thing, you could see file or directory history and info by accessing something like `foo.c@@/versions/5` (which isn't ordinarily visible when listing its directory). Pretty nifty.
Your workspaces were also copy-on-write from the base file revisions you were using.
We used Clearcase around year 2000 on HP-UX. I found it nice and powerful, but 90% of the developers did not understand it. Well, probably a similar statement holds for git.
I certainly didn’t understand it. We were using it up to 2019. A coworker set up a spec that would automatically mirror to the main codebase, unknown to me that was possible. I made a branch there, did some stuff, and then reverted. Little did I know I was essentially working on production. Broke a bunch of stuff and had to remember what I changed because there was no history. Point is it was too powerful for people that did and didn’t know how to use it.
> But FUSE is pretty annoying to use on Mac – you need to install a kernel extension, and Mac OS seems to be making it harder and harder to install kernel extensions
I'm not a Mac user at all, so there may be reasons what I'm about to suggest is silly beyond the ones I will mention myself, but…
Another way around this is to run the FUSE filesystem in a small VM running a different OS that is more FUSE friendly, then export that filesystem to MacOS using a network filesystem that it natively understands. This may also be NFS so you aren't avoiding NFS if so, but you at least separate the NFS issues from the issues interfacing git (assuming interfacing git with FUSE doesn't have just as many gotchas as using NFS directly).
There are a couple of obvious potential performance issues here. Firstly adding the extra network filesystem layer will likely add a noticeable amount of latency for all operations. You likely have this twice too: if you are reading a repo from the host machine rather than checking out its own copy (which would likely be a significant inconvenience) then the VM will need to access that somehow. Secondly any caching in RAM that the fs->git layer does will mean allocating enough RAM to the VM for that which will be dedicated so not available to other processes on your bare metal. If the amount of memory required is small anyway then this is not a problem, or if letting it swap out to disk (or using a disk based cache in the first place) is significantly less inefficient than constantly rereading+reprocessing the structure that the cache is intended to speed references to, then that is an option too.
26 comments
[ 2.6 ms ] story [ 40.6 ms ] threadThe two filesystems I could that were natively supported by Mac OS were WebDav and NFS. I couldn’t tell which would be easier to implement so I just tried both”
I might find out that it is incomplete, buggy or a nuisance to use, but FSKit (https://developer.apple.com/documentation/FSKit) would be my first choice.
The DIRECTORY/checkins/ directory doesn't list out anything by itself, but you can look things up by any of the supported checkin names (hash, tag, branch, date...): https://fossil-scm.org/home/doc/trunk/www/checkin_names.wiki
i feel like some of the old-school commands will benefit from long args, e.g., '--search'. at the time of writing, the current `git log` documentation[1]'s `-S' has _one_ instance of the word 'search'.
(un)related to the article, author went on to contribute documentation updates to git, which were much needed [2]
[1]: https://git-scm.com/docs/git-log#Documentation/git-log.txt--... [2]: https://jvns.ca/blog/2026/01/08/a-data-model-for-git/
“git grep” is the correct tool for Julia’s grep, however as usual it has the worst defaults: the work tree (so it’s just a slightly better “grep”), you need to give it a list of revisions to search to get a history search (so usually you pipe-xargs a rev-list into it).
Making it into an NFSv4 server should also be pretty easy.
FUSE-bindings for "filesystems in bash", eg:
https://github.com/zevweiss/booze/blob/master/cowsayfs.sh#L5...
...I think that WebDAV is "the way" compared to FUSE, but I'm always intrigued by the idea of virtual filesystems as an implementation face.By the way, it is still around.
But... yes... this is just using NFS locally to see what's already in GIT, which is perfectly find and as Julia says, allows you to appreciate the structure of the git repo. Ignore this old man yelling at clouds.
Yes, it was, is, quite complex and requires a dedicated team, however there are plenty of features that are still to be made available as easyly.
I loved my view configurations, there were some tricks we could do for mix and match what code to see, and the build caches to this day is still not as integrated as sharing object and library files was back then.
The tree/blob ID is already a hash though. You don't need to hash it again. Just use the first 8 bytes of the tree ID as the inode.
Your workspaces were also copy-on-write from the base file revisions you were using.
Of the top of my head only one port is needed for V4.
I'm not a Mac user at all, so there may be reasons what I'm about to suggest is silly beyond the ones I will mention myself, but…
Another way around this is to run the FUSE filesystem in a small VM running a different OS that is more FUSE friendly, then export that filesystem to MacOS using a network filesystem that it natively understands. This may also be NFS so you aren't avoiding NFS if so, but you at least separate the NFS issues from the issues interfacing git (assuming interfacing git with FUSE doesn't have just as many gotchas as using NFS directly).
There are a couple of obvious potential performance issues here. Firstly adding the extra network filesystem layer will likely add a noticeable amount of latency for all operations. You likely have this twice too: if you are reading a repo from the host machine rather than checking out its own copy (which would likely be a significant inconvenience) then the VM will need to access that somehow. Secondly any caching in RAM that the fs->git layer does will mean allocating enough RAM to the VM for that which will be dedicated so not available to other processes on your bare metal. If the amount of memory required is small anyway then this is not a problem, or if letting it swap out to disk (or using a disk based cache in the first place) is significantly less inefficient than constantly rereading+reprocessing the structure that the cache is intended to speed references to, then that is an option too.