- Untuk memahami struktur internal sistem kontrol versi, penulis mencoba mengimplementasikan sendiri sistem yang mirip Git
- Menggunakan hash SHA-256 dan kompresi zstd untuk menggantikan SHA-1 dan zlib milik Git, serta menyusun repositori dengan struktur direktori
.tvc
- Ditulis dengan Rust, dan fitur hash file, kompresi, commit, checkout diimplementasikan secara bertahap
- Objek commit mencakup hash tree, commit induk, penulis, dan pesan, serta file yang sama tidak disimpan ulang berkat pencegahan duplikasi hash
- Dengan mengalaminya langsung, penulis menekankan bahwa Git adalah penyimpanan file berbasis alamat konten
Metode hashing dan kompresi
- Git mengidentifikasi semua objek dengan hash SHA-1, tetapi proyek ini menggunakan SHA-256
- SHA-1 sudah tua dan memiliki kelemahan keamanan, tetapi dalam proyek ini hanya dipakai untuk mengidentifikasi isi file sehingga keamanan bukan faktor penting
- Sebagai pengganti zlib milik Git, dipilih pustaka kompresi zstd dari Facebook
- zstd dinilai lebih efisien, dan kompatibilitas dengan Git memang bukan tujuan proyek ini
- Nama proyeknya adalah “tvc (Tony’s Version Control)”, dengan file
.tvc dan .tvcignore digunakan sebagai padanan struktur Git
Tahapan implementasi
- Urutan implementasinya adalah membaca argumen perintah → membaca aturan ignore → menampilkan daftar file → hashing dan kompresi → membuat tree dan commit → mengelola HEAD → checkout commit
- Ditulis dengan Rust, dan perintah
ls menerapkan aturan .tvcignore untuk menelusuri file yang tidak diabaikan secara rekursif lalu menampilkan hash SHA-256 tiap file
- Dengan pustaka zstd, fitur kompresi dan dekompresi file diimplementasikan secara sederhana
Struktur commit
- Objek commit memuat informasi berikut
- Jenis objek (“commit”)
- Keadaan sistem file saat itu (hash tree)
- Commit sebelumnya (HEAD)
- Penulis (author)
- Pesan commit
- Berbeda dari Git, proyek ini tidak membedakan author dan committer, serta tidak mengimplementasikan fitur merge atau rebase
- Saat membuat commit, objek tree dibuat, di-hash, dikompresi, lalu disimpan ke
.tvc/objects/, dan file HEAD diperbarui
- File yang sama tidak disimpan ulang jika hash-nya sama, sehingga duplikasi penyimpanan dapat dicegah
Objek tree dan checkout
- Fungsi
generate_tree() menelusuri direktori, lalu melakukan hash, kompresi, dan penyimpanan untuk tiap file, serta menyusun nama file dan hash menjadi string
- Subdirektori diproses secara rekursif untuk membentuk struktur tree
- Objek commit dan tree di-parse ke dalam struct (
Commit, Tree) agar lebih mudah ditangani di memori
- Fungsi
generate_fs() merekonstruksi sistem file berdasarkan struktur tree dan melakukan checkout ke path yang ditentukan
Pelajaran dari proyek ini
- Penulis merasakan langsung bahwa Git adalah penyimpanan file berbasis alamat konten (key-value)
- Bagian tersulit adalah parsing format objek, dan berikutnya penulis berencana memakai format yang lebih jelas seperti YAML atau JSON
- Seluruh kode tersedia di repositori GitHub(tonystr/t-version-control)
1 komentar
Komentar Hacker News
Menarik bahwa Git adalah satu-satunya SCM yang mendukung recursive merge strategy
Metode ini secara otomatis mengingat riwayat penyelesaian konflik sebelumnya, jadi sangat berguna
Banyak orang masih lebih memilih rebase, tetapi saat mengimplementasikan merge, mekanisme penyimpanan riwayat penyelesaian konflik wajib ada
Referensi terkait: Merge made by recursive strategy
Referensi: Git Tools - Rerere
Tautan
git mergetidak punya strategi “null”Bahkan ketika konflik sudah diselesaikan dan saya hanya ingin meninggalkan catatan merge, Git tetap berusaha membantu
Akan bagus jika ada opsi yang sekadar mencatat fakta merge tanpa menyentuh index atau worktree
Misalnya Pijul melakukan hal itu
Kita jadi tidak bisa melihat berbagai percobaan di beberapa commit, lebih sulit untuk rollback, dan sulit melanjutkan pekerjaan tambahan pada branch yang sudah di-merge
Ketika beberapa PR adalah bagian dari satu puzzle, menurut saya merge biasa jauh lebih baik
Mempelajari cara kerja internal alat yang dipakai setiap hari selalu menyenangkan
Khususnya Git from the Bottom Up adalah tulisan luar biasa yang menjelaskan struktur internal Git dengan jelas
Dalam sekitar 20 menit, kita bisa memahami mekanisme buram di balik perintah Git
cat-file, dan itu cukup kerenJika penasaran bagaimana coding agent menyusun rencana, tulisan seperti ini adalah bagian dari data pelatihan mereka
Namun kalau penulisnya sendiri dibantu LLM, situasinya bisa jadi melingkar
Sepertinya memang ada bot yang mengeruk repositori publik
Rasanya aneh membayangkan kode saya dipakai untuk melatih LLM
Artikelnya sendiri tidak berisi output LLM, tetapi saya memakai ChatGPT saat meminta saran tentang konvensi kode Rust atau perbandingan algoritme
Tutorial CodeCrafters “Build your own Git” benar-benar luar biasa
Saya juga merekomendasikan video live Jon Gjengset yang mengimplementasikannya langsung dengan Rust
Saya juga berharap version control lebih banyak dipakai di bidang selain software
GotVC adalah proyek menarik dengan E2E encryption, import paralel, dan struktur yang mendukung file berukuran besar
Pada akhirnya harus dibuka dan dibandingkan dengan program aslinya
Tulisan ini mengingatkan saya pada ugit: DIY Git in Python
Ini salah satu materi terbaik yang menggali internal Git secara mendalam tetapi tetap mudah diikuti
Sapling VCS, fork Mercurial dari Meta, menggunakan kompresi Zstd dictionary
Di dokumentasi penjelasannya, ini bisa dibandingkan dengan delta-compressed packfile milik Git
Pada repositori kecil, delta compression Git lebih efisien, tetapi pada repositori besar, kompresi dictionary berbasis path lebih baik
Baru-baru ini Git juga menambahkan fitur serupa bernama “path-walk”
Saya juga pernah mencoba hal serupa, dan nama proyek saya adalah “shit”
Tautan GitHub
Dulu saya pernah mencoba membuat framework SPA dan terkejut dengan kompleksitas tersembunyi di dalamnya
Sepertinya pengembang React atau Angular juga pernah masuk ke lubang kelinci seperti ini
Git juga sama, sangat pandai menyembunyikan kompleksitasnya
Saya pernah melihat klien Git yang ditulis dalam PHP; ia bisa membaca packfile dan reftable, serta mendukung diff berbasis LCS
gipht-horse
Dan saya baru tahu bahwa
@bisa dipakai menggantikan HEAD, yang secara sintaks ternyata cukup masuk akal