Sepanjang course ini kita sudah menjalankan ratusan perintah Git — add, commit, branch, merge — dan menerima hasilnya begitu saja. Section penutup Hooks dan Otomasi menutup dengan pertanyaan yang belum terjawab: bagaimana Git bekerja di dalam? Mengapa hash yang tampak acak bisa menjadi identitas yang unik, dan mengapa repository tidak membengkak meski menyimpan setiap versi setiap berkas? Jawabannya berada pada satu desain: seluruh data yang Git simpan — isi berkas, struktur folder, riwayat commit, tag — hanyalah objek di dalam sebuah database. Chapter ini membuka database itu dan memperkenalkan penghuninya.

Filosofi: Satu Database Objek #

Chapter Git Directory sudah memperlihatkan bahwa isi riwayat hidup di objects/ dan ditunjuk oleh refs/. Sekarang kita masuk lebih dalam: Git bukan penyimpan berkas bernama, melainkan database content-addressable — setiap potong data dialamatkan oleh hash yang dihitung dari isinya sendiri, sehingga isi identik selalu berakhir pada alamat yang sama. Hanya ada empat jenis objek di dalam database ini:

Jenis objekIsinyaPerannya
blobIsi berkas mentah, tanpa nama berkasSatu versi isi satu berkas
treeDaftar entri: mode, hash, namaStruktur folder pada satu titik waktu
commitMetadata + satu tree root + parentSatu titik riwayat beserta pesannya
tagMetadata + penunjuk ke objek lainTag annotated lengkap dengan pembuatnya

Karena hanya ada empat jenis ini, memahami Git berarti memahami empat struktur kecil dan cara saling merujuknya. Perintah apa pun — dari git add sampai merge paling rumit — pada akhirnya hanya membaca dan menulis keempat jenis objek itu, plus penunjuk-penunjuk refs yang akan kita bedah pada chapter References dan Refs .

Membangun Repository Latihan #

Kita pakai repository kecil yang sama dengan pola latihan sebelumnya: dua commit dan satu tag annotated. Bangun ulang dari nol agar keluaran kita identik:

bash
mkdir latihan-model && cd latihan-model
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'Toko Kopi Senja\n' > README.md
git add README.md
git commit -m "Buat toko"
mkdir src
printf 'espresso 18000\n' > src/menu.txt
git add src/menu.txt
git commit -m "Tambah daftar menu"
git tag -a v1.0.0 -m "Rilis pertama"
git log --oneline

Output yang Dihasilkan:

text
455518b Tambah daftar menu
1697160 Buat toko

Dua commit dan satu tag — cukup untuk menghadirkan keempat jenis objek.

git cat-file: Membedah Jenis Objek #

Perintah git cat-file -t melaporkan jenis objek dari alamat mana pun. Kita uji keempat jenisnya sekaligus pada repository latihan:

bash
git cat-file -t HEAD

Output yang Dihasilkan:

text
commit
bash
git cat-file -t HEAD^{tree}

Output yang Dihasilkan:

text
tree
bash
git cat-file -t HEAD:README.md

Output yang Dihasilkan:

text
blob
bash
git cat-file -t v1.0.0

Output yang Dihasilkan:

text
tag

Empat perintah, empat jenis: HEAD berjenis commit, tree root-nya berjenis tree, isi README.md berjenis blob, dan tag v1.0.0 yang kita buat dengan -a berjenis objek tersendiri. Notasi HEAD^{tree} berarti “tree yang ditunjuk commit HEAD”, dan HEAD:README.md berarti “objek pada path README.md di snapshot HEAD” — dua bentuk alamat yang akan sering kita pakai di sepanjang section ini. Jumlah objek totalnya bisa dihitung:

bash
git count-objects

Output yang Dihasilkan:

text
8 objects, 32 kilobytes

Delapan objek untuk dua commit: dua commit, tiga tree (dua versi tree root plus satu tree untuk folder src/), dua blob, dan satu objek tag. Seluruh riwayat repository ini memang hanya segini — tidak ada berkas tersembunyi lain.

Struktur Direktori .git/objects #

Objek-objek itu tersimpan sebagai berkas lepas (loose object) di dalam .git/objects, dengan nama berkas yang dipecah dua:

bash
ls .git/objects

Output yang Dihasilkan:

text
16
35
45
58
70
c6
d4
e8
info
pack

Delapan nama dua karakter adalah folder — dua karakter pertama dari hash objek — sedangkan info dan pack menampung pengaturan penyimpanan. Kita buka satu folder milik blob README.md:

bash
ls .git/objects/e8

Output yang Dihasilkan:

text
6980e618bbec64678d440b7116f5c47af02d1a

Nama berkas itu adalah 38 karakter sisanya: digabungkan dengan nama foldernya terbentuk hash utuh e86980e6... — persis blob README.md yang kita periksa tadi. Pemecahan xx/38hex menjaga folder objects/ tetap rapi meski jumlah objek membengkak; pack menjadi rumah objek terkompresi yang dibahas pada chapter Packfiles . Bandingkan alamat commit aktif dari berkas ref-nya:

bash
cat .git/refs/heads/main

Output yang Dihasilkan:

text
455518b28637c16916025256825c0986c1be377f

Hash tersebut identik dengan commit “Tambah daftar menu” — folder 45 di daftar objects di atas memang tempat objek commit itu tinggal. Relasi keempat jenis objek di repository ini terpetakan berikut:

Satu commit menunjuk satu tree root; tree root menunjuk blob dan tree anak; commit kedua menunjuk commit pertama sebagai parent; tag menunjuk commit. Rantai sesederhana itu menampung seluruh keadaan proyek — diagram ini adalah peta yang kita telusuri objek demi objek pada chapter berikutnya.

Semua Perintah Hanyalah Manipulasi Objek dan Refs #

Inilah insight yang mengubah cara memandang Git: karena seluruh datanya cuma objek dan penunjuk, setiap perintah sehari-hari hanyalah kombinasi operasi database sederhana:

Perintah sehari-hariYang sebenarnya dikerjakan
git add menu.txtHitung hash isi berkas, simpan objek blob, catat pasangan path-hash di index
git commitTulis objek tree dari index, tulis objek commit, geser isi refs/heads/main
git branch fiturTulis berkas refs/heads/fitur berisi hash saat ini
git tag -a v1.0.0Tulis objek tag, tulis berkas refs/tags/v1.0.0 menunjuknya
git switch fiturTulis ulang berkas HEAD agar menunjuk refs/heads/fitur

Dokumentasi resmi menyebut perintah-perintah level rendah ini plumbing (pipa saluran) dan perintah ramah pengguna sebagai porcelain (keramik halus di atasnya) — pembagian yang berasal dari desain asli Git, dijelaskan pada bab Git Internals Pro Git. Ketika porcelain macet, plumbing selalu tersedia sebagai jalan manual — kita akan memakainya nyata untuk menulis blob tanpa git add.

Empat jenis objek sudah dikenali; yang belum kita lakukan adalah membuka masing-masing dan membaca isinya baris demi baris. Chapter berikutnya, Blob, Tree, Commit, dan Tag , membedah keempatnya sampai ke byte terakhir.