Điều gì nếu mỗi commit git chỉ là một thư mục bạn có thể duyệt qua?
Julia Evans xây git-commit-folders: mount repo git qua NFS, mỗi commit trở thành thư mục thật sự - có thể grep, vim, hay pipe vào bất kỳ công cụ nào.

Mỗi lần muốn xem một file từ branch khác, tôi lại phải làm cái điệu múa quen thuộc. Mở notes ra. Tìm “git show file trên branch khác”. Tìm thấy câu trả lời Stack Overflow từ năm 2011. Copy lệnh. Đọc nhầm cú pháp dấu hai chấm. Lỗi. Thử lại. Cuối cùng lấy được file, cảm thấy hơi thất bại.
Tôi không tệ môn git. Não tôi chỉ từ chối ghi nhớ git show branch-khác:đường/dẫn/file.go mà thôi.
Julia Evans có vẻ gặp vấn đề tương tự. Và thay vì viết cheatsheet, bà ấy dựng cả một NFS server.
Ý tưởng cốt lõi: commit là thư mục, hãy làm nó thật sự như vậy
Commit git thực sự hoạt động như thư mục. Mỗi commit trỏ đến một tree object - về cơ bản là danh sách đệ quy các file và thư mục con. Lý do duy nhất bạn không thể duyệt ~/.git như filesystem là vì git lưu mọi thứ ở dạng binary objects để tiết kiệm dung lượng đĩa.
git-commit-folders loại bỏ lớp trừu tượng đó. Chạy nó trên một repo và nó mount một filesystem ảo, mỗi commit hash trở thành một thư mục thật:
$ ls commits/8d/8dc0/8dc0cb0b4b0de3c6f40674198cb2bd44aeee9b86/
README
$ ls commits/c9/c94e/c94e6f531d02e658d96a3b6255bbf424367765e9/
_config.yml config.rb Rakefile rubypants.rb source
Branch và tag chỉ là symlink trỏ đến thư mục commit:
$ ls -l branches/
lrwxr-xr-x main -> ../commits/04/043e/043e90debbeb0fc6b4e28cf8776e874aa5b6e673
lrwxr-xr-x feature-x -> ../commits/91/912d/912da3150d9cfa74523b42fae028bbb320b6804f
Giờ thì bài toán “xem file trên branch khác” trở thành:
vim branches/branch-khac/go.mod
Không cần nhớ cú pháp git. Chỉ là đường dẫn file.
Tại sao cách này lại có ích (dù git grep đã tồn tại)
Julia thẳng thắn thừa nhận đây không phải cách hiệu quả nhất. git show, git log -S, git grep đều có sẵn. Nhưng:
| Tác vụ | Cách git thường | Cách dùng filesystem |
|---|---|---|
| Tìm hàm đã xóa | git log -S 'funcName' --all -- file.go |
grep -r funcName branch_histories/main/*/file.go |
| Xem file trên branch khác | git show branch:đường/dẫn/file |
vim branches/branch-khac/đường/dẫn/file |
| Tìm kiếm trên tất cả branch | git grep pattern $(git branch -a) |
grep -r pattern branches/*/commit.go |
Lệnh git mạnh hơn - có thể lọc theo ngày, tác giả, nội dung patch. Nhưng cách dùng filesystem thì không cần nhớ gì hết. Mọi công cụ bạn đã biết (grep, find, diff, vim) đều hoạt động ngay.
Nhưng kỹ thuật không đơn giản chút nào
Julia muốn cái này chạy được trên macOS mà không cần kernel extension. Điều đó loại FUSE ra khỏi danh sách. Hai giao thức filesystem native còn lại trên macOS là WebDAV và NFS.
Bà thử WebDAV trước. Thư viện chuẩn Go có sẵn WebDAV. Trông khả thi. Rồi gặp bẫy: x/net/webdav dùng io/fs, mà io/fs không hỗ trợ symlink. Branch sẽ phải là thư mục thật thay vì symlink - phá vỡ toàn bộ mental model.
Vậy là chuyển sang NFS. NFSv3 cụ thể, qua thư viện go-nfs.
Kết quả là một nhật ký kỹ thuật sâu 9 vấn đề:
- Vấn đề 3 (liệt kê hàng triệu commit): Tổ chức theo 2 ký tự prefix, giống cách
.git/objectslàm, rồi cache toàn bộ hash commit đã pack vào memory. Hoạt động được trên Linux kernel với ~1 triệu commit. Mất khoảng một phút khởi động lần đầu, sau đó cập nhật nhanh. - Vấn đề 4 (lỗi “Not a directory”): Đây là cách NFS báo bất kỳ lỗi liệt kê thư mục nào, không phải sai kiểu dữ liệu. Phải dùng Wireshark mới chẩn đoán được.
- Vấn đề 5 (inode numbers): Julia vô tình đặt mọi inode thư mục về 0.
findnhận ra khi mọi thư mục có cùng inode và từ chối đệ quy, cho rằng có vòng lặp filesystem - điều này hoàn toàn hợp lý. - Vấn đề 6 (stale file handles): Vẫn chưa giải quyết được. NFS cần map 64-byte opaque handles sang file đúng, nhưng thư viện go-nfs dùng cache cố định bị tràn trên repo lớn.
Đây là điều tôi thích ở cách Julia viết: bà không dọn dẹp đống thất bại. Bài viết đọc như nhật ký debug, và những thứ chưa sửa được vẫn nằm nguyên trong danh sách.
Tại sao HN đào lại bài này vào năm 2026
Người submit (pvtmert) nói thẳng:
“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.”
Đây mới là góc nhìn thú vị. AI coding agent không vất vả với cú pháp git show - nhưng lại gặp khó với các lệnh git plumbing tùy tiện không được biểu diễn kỹ trong training data, hoặc cần parse binary output. Một filesystem thuần túy mà mọi công cụ đều đọc được là interface đơn giản hơn nhiều cho agent đang điều hướng qua lịch sử code.
Thread HN cũng nhắc đến ClearCase (hệ thống version control doanh nghiệp ra đời trước git) có thứ tương tự: bạn có thể truy cập foo.c@@/versions/5 như một đường dẫn thông thường. Fossil cũng có lệnh fusefs làm điều này.
Và một commenter, steveBK123, tóm gọn sự hoài nghi trong ba chữ:
“NFS.. stop right there”
Không phải không có lý. NFS nổi tiếng với những edge case kỳ lạ. Nhưng khi phương án thay thế là FUSE với kext hoặc không-xây-gì-hết, lựa chọn của Julia hoàn toàn ổn.
Nên xem không?
Đọc bài gốc nếu:
- Bạn viết công cụ điều hướng lịch sử git bằng code
- Bạn tò mò về cách object model của git ánh xạ lên filesystem
- Bạn xây AI coding tools và đang nghĩ về cách agent truy cập context code cũ
- Bạn là fan Julia Evans và muốn xem ai đó ghi lại cẩn thận 9 cách NFS làm khó cuộc sống
Bỏ qua nếu:
git showvàgit log -Sđã nằm trong cơ bắp bạn rồi- Bạn cần truy cập lịch sử git cho môi trường production (có công cụ VFS tốt hơn)
- Repo của bạn có hàng triệu commit và bạn không muốn chờ 1 phút mỗi lần khởi động
Dự án này thực nghiệm và Julia nói thẳng điều đó. Nhưng công cụ thực nghiệm giúp bạn hiểu cách thứ gì đó vận hành thường là loại tốt nhất.
Thảo luận trên Hacker News · Nguồn: jvns.ca · Đăng bởi pvtmert
Bài viết liên quan
AutoResearch Giải Thích: Vì Sao Karpathy Đóng Góp Cho AI Scientist Này
Mổ xẻ AutoResearch: kiến trúc AI scientist đa mô hình, cơ chế Ralph loop hồi phục trạng thái và lý do Karpathy trực tiếp đóng góp vào repo.
Từ điển prompt thực chiến cho AI Coding Agent: Nói sao cho chuẩn tech?
Bộ từ điển tra cứu thực chiến giúp bạn chuyển hóa các câu lệnh đời thường thành thuật ngữ kiến trúc chuẩn xác khi làm việc với AI Coding Agent.
Những thuật ngữ thượng đẳng để coding với AI Agent sướng hơn
Khám phá các thuật ngữ kiến trúc và kỹ thuật lập trình đòn bẩy cao giúp bạn prompt AI Coding Agent chính xác, loại bỏ ảo giác và viết code chuẩn senior.
AI DevKit là gì: lớp control plane cho AI coding agent - và giới hạn của nó
Giải mã AI DevKit: lớp control plane điều phối coding agent với TUI console, cấu hình tập trung, bộ nhớ SQLite và các skill quy trình kỹ thuật chuẩn hóa.