Database objek Git kini terbuka: blob, tree, commit, dan tag yang saling menunjuk lewat alamat hasil perhitungan isi. Tapi alamat seperti bd460ab5... mustahil dihafal manusia — kita bekerja dengan nama: main, v1.0.0, origin/main. Lapisan penerjemah nama-ke-alamat bernama refs (references), dan bab ini membongkarnya sampai ke berkasnya: branch ternyata berkas teks 41 byte, remote tracking branch tinggal di folder sendiri, dan riwayat pergerakan tiap penunjuk tercatat di reflog. Kita juga menyaksikan ratusan refs diringkas menjadi satu berkas packed-refs oleh git gc.
Refs Adalah Berkas Berisi Satu Hash #
Chapter Konsep Branch sudah membocorkan bahwa branch adalah penunjuk; kini kita telusuri seluruh keluarganya. Bangun repository latihan dengan tiga commit, branch bersarang, dua jenis tag, dan satu remote lokal:
mkdir latihan-refs && cd latihan-refs
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'Keranjang:\n- kopi\n' > keranjang.md
git add keranjang.md
git commit -m "Buat keranjang belanja"
printf 'Keranjang:\n- kopi\n- gula\n' > keranjang.md
git add keranjang.md
git commit -m "Tambah gula"
git tag v0.9.0
printf 'Keranjang:\n- kopi\n- gula\n- teh\n' > keranjang.md
git add keranjang.md
git commit -m "Tambah teh"
git branch fitur/opsi-gelap HEAD~1
git tag -a v1.0.0 -m "Rilis pertama"
git init --bare ../latihan-refs-origin.git
git remote add origin ../latihan-refs-origin.git
git push origin mainSeluruh penunjuk hidup di bawah folder .git/refs:
ls -R .git/refs/heads .git/refs/tags .git/refs/remotesOutput yang Dihasilkan:
.git/refs/heads:
fitur
main
.git/refs/heads/fitur:
opsi-gelap
.git/refs/remotes:
origin
.git/refs/remotes/origin:
main
.git/refs/tags:
v0.9.0
v1.0.0Peta lengkapnya terlihat dari nama jalurnya: dua branch lokal (satu di folder bersarang fitur/), satu branch pelacak remote, dan dua tag. Isi berkas-berkas itu kita baca semua sekaligus:
for f in .git/refs/heads/main .git/refs/heads/fitur/opsi-gelap .git/refs/tags/v0.9.0 .git/refs/tags/v1.0.0 .git/refs/remotes/origin/main; do echo "--- $f"; cat "$f"; doneOutput yang Dihasilkan:
--- .git/refs/heads/main
bd460ab5fa50718df5a58b3cacb77fc48726c426
--- .git/refs/heads/fitur/opsi-gelap
727986b34a40d16d73b0991e5facb9534926d029
--- .git/refs/tags/v0.9.0
727986b34a40d16d73b0991e5facb9534926d029
--- .git/refs/tags/v1.0.0
4745b1e9824dac02120dd6202098e880d8a71b21
--- .git/refs/remotes/origin/main
bd460ab5fa50718df5a58b3cacb77fc48726c426Lima berkas, lima hash — dan tiap hash punya cerita. main menunjuk commit “Tambah teh”; fitur/opsi-gelap dan tag ringan v0.9.0 sama-sama menunjuk commit “Tambah gula” (branch dibuat di HEAD~1, tag ditempel setelah commit itu); origin/main menunjuk commit yang sama dengan main karena barusan kita push. Tag v1.0.0 adalah satu-satunya yang beda isi: hash 4745b1e... adalah objek tag dari chapter Blob, Tree, Commit, dan Tag
— annotated tag menunjuk objek tag, objek tag yang menunjuk commit.
Peta posisi semua penunjuk bisa dicek dari satu perintah:
git log --oneline --all --decorateOutput yang Dihasilkan:
bd460ab (HEAD -> main, tag: v1.0.0, origin/main) Tambah teh
727986b (tag: v0.9.0, fitur/opsi-gelap) Tambah gula
7dece8b Buat keranjang belanjaNamespace dan Hierarki #
Struktur folder refs bukan kebetulan — Git membagi penunjuk berdasarkan namespace, dan garis miring membuat sub-folder sehingga nama bisa bersarang tanpa tabrakan (refs/heads/fitur/opsi-gelap dan refs/heads/fitur/kecepatan hidup berdampingan):
| Namespace | Menunjuk ke | Dibuat oleh |
|---|---|---|
refs/heads/ | Branch lokal (commit) | git branch, git commit |
refs/tags/ | Tag ringan (commit) atau annotated (objek tag) | git tag |
refs/remotes/ | Salinan branch remote hasil fetch/push | git fetch, git push |
HEAD | Bukan folder — berkas istimewa posisi kita sekarang | git switch |
refs/remotes/origin/main adalah remote-tracking branch yang bekerja persis seperti dijelaskan pada Remote-Tracking Branch
: potret posisi branch main di server origin saat terakhir dihubungi. Namespace lain juga ada — refs/stash untuk simpanan sementara, refs/notes/ untuk anotasi — semuanya mengikuti pola yang sama: nama di folder, hash di dalam.
rev-parse: Penerjemah Semua Bentuk Nama #
Perintah git rev-parse adalah penerjemah resmi dari bentuk nama apa pun menjadi hash utuh. Tag annotated menyimpan kejutan kecil:
git rev-parse v1.0.0Output yang Dihasilkan:
4745b1e9824dac02120dd6202098e880d8a71b21git rev-parse v1.0.0^{commit}Output yang Dihasilkan:
bd460ab5fa50718df5a58b3cacb77fc48726c426Nama v1.0.0 diselesaikan ke objek tag, bukan commit — akhiran ^{commit} mengupasnya sampai ke commit yang ditunjuk. Bentuk-bentuk lain dari repository yang sama:
| Bentuk | Diselesaikan menjadi | Hasil |
|---|---|---|
main | Isi refs/heads/main | bd460ab... |
v1.0.0 | Objek tag | 4745b1e... |
v1.0.0^{commit} | Commit di balik tag | bd460ab... |
main~1 | Parent dari main | 727986b... |
HEAD | Diselesaikan lewat berkas HEAD | bd460ab... |
Mekanisme resolusi inilah yang bekerja diam-diam setiap kali kita mengetik git show main, git diff main~1, atau git log v1.0.0 — Git menerjemahkan dulu, baru membuka objeknya. Nama pendek seperti main atau v1.0.0 sebenarnya disingkat: aturan urutannya Git mencari main di refs/tags, refs/heads, lalu hash singkat — bab Git References
Pro Git merinci urutan lengkapnya.
Reflog: Riwayat Pergerakan Tiap Ref #
Refs bergerak terus — commit menggeser main, switch memindahkan HEAD — dan Git mencatat setiap pergerakan itu di reflog. Foldernya bisa kita lihat strukturnya:
ls -R .git/logsOutput yang Dihasilkan:
.git/logs:
HEAD
refs
.git/logs/refs:
heads
remotes
.git/logs/refs/heads:
fitur
main
.git/logs/refs/heads/fitur:
opsi-gelap
.git/logs/refs/remotes:
origin
.git/logs/refs/remotes/origin:
mainStruktur .git/logs mencerminkan .git/refs: tiap ref yang pernah bergerak punya berkas log sendiri. Isi .git/logs/HEAD kita bedah baris per baris:
cat .git/logs/HEADOutput yang Dihasilkan:
0000000000000000000000000000000000000000 7dece8ba93661ee80d764daedd1fa41464395b2c Budi Santoso <[email protected]> 1793934000 +0700 commit (initial): Buat keranjang belanja
7dece8ba93661ee80d764daedd1fa41464395b2c 727986b34a40d16d73b0991e5facb9534926d029 Budi Santoso <[email protected]> 1793934300 +0700 commit: Tambah gula
727986b34a40d16d73b0991e5facb9534926d029 bd460ab5fa50718df5a58b3cacb77fc48726c426 Budi Santoso <[email protected]> 1793934600 +0700 commit: Tambah tehTiap baris memuat lima potong informasi: posisi lama, posisi baru, identitas pelaku, stempel waktu, lalu aksi dan pesannya (dipisahkan tab dari stempel waktu). Baris pertama mencatat HEAD bergerak dari hash nol — commit pertama belum punya posisi sebelumnya. Reflog inilah jaring pengaman di balik git reflog dan seluruh pemulihan commit “hilang” pada Git Reflog
— objek yang sudah tak ditunjuk refs mana pun tetap bisa ditemukan lewat catatan ini. Tampilan ringkasnya:
git reflogOutput yang Dihasilkan:
bd460ab HEAD@{0}: commit: Tambah teh
727986b HEAD@{1}: commit: Tambah gula
7dece8b HEAD@{2}: commit (initial): Buat keranjang belanjapacked-refs: Ratusan Penunjuk, Satu Berkas #
Kelemahan refs lepas muncul di repository besar: satu berkas per ref berarti ribuan berkas kecil — tiap pembacaan refs menjadi satu operasi sistem berkas. git gc merapikannya dengan mengemas seluruh refs ke satu berkas terurut:
git gc -q
ls -R .git/refsOutput yang Dihasilkan:
.git/refs:
heads
remotes
tags
.git/refs/heads:
fitur
.git/refs/heads/fitur:
.git/refs/remotes:
origin
.git/refs/remotes/origin:
.git/refs/tags:Folder-folernya masih ada tapi kosong — berkas main sudah tidak ada:
cat .git/refs/heads/mainOutput yang Dihasilkan:
cat: .git/refs/heads/main: No such file or directorySeluruh isi pindah ke .git/packed-refs:
cat .git/packed-refsOutput yang Dihasilkan:
# pack-refs with: peeled fully-peeled sorted
727986b34a40d16d73b0991e5facb9534926d029 refs/heads/fitur/opsi-gelap
bd460ab5fa50718df5a58b3cacb77fc48726c426 refs/heads/main
bd460ab5fa50718df5a58b3cacb77fc48726c426 refs/remotes/origin/main
727986b34a40d16d73b0991e5facb9534926d029 refs/tags/v0.9.0
4745b1e9824dac02120dd6202098e880d8a71b21 refs/tags/v1.0.0
^bd460ab5fa50718df5a58b3cacb77fc48726c426Baris pertama berjudul # pack-refs with: peeled fully-peeled sorted — tiga sifat berkas ini. Setiap baris berikut memasangkan hash dan nama ref dalam satu spasi, terurut agar pencarian cepat. Baris berawalan ^ adalah hasil peeled: objek tag v1.0.0 dikupas menjadi commit yang ditunjuknya bd460ab..., disimpan sebagai jawaban siap pakai sehingga Git tak perlu membuka objek tag setiap kali tag ini diperlukan. Kemasan ini transparan total:
git rev-parse mainOutput yang Dihasilkan:
bd460ab5fa50718df5a58b3cacb77fc48726c426git symbolic-ref HEADOutput yang Dihasilkan:
refs/heads/maingit rev-parse main tetap menemukan bd460ab... — kini dari packed-refs — dan git symbolic-ref HEAD tetap membaca berkas HEAD yang memang tidak ikut dikemas. Refs lepas dan terkemas hidup berdampingan: ref yang bergerak ditulis ulang sebagai berkas lepas, lalu dikemas lagi pada git gc berikutnya.
Di antara semua penunjuk ini, satu berkas istimewa menempati posisi teratas: HEAD — penunjuk yang menjawab “kita sedang berada di mana”. Berkas itu terkadang berisi ref: refs/heads/main, terkadang berisi hash telanjang — dua wajah yang menentukan apakah pekerjaan kita aman atau terancam. Chapter berikutnya, HEAD dan Detached HEAD
, membedah kedua wajahnya.