Kita sudah bisa membuat commit dengan siklus add–commit dari section sebelumnya, dan git log menampilkannya dalam format yang rapi: penulis, tanggal, lalu pesan. Tampilan yang rapi itu hanyalah kulitnya. Di dalamnya, sebuah commit adalah objek mentah berisi lima bagian — tree, parent, author, committer, dan pesan — yang saling merujuk lewat hash. Membedah objek mentah ini menjawab pertanyaan yang selama ini kita terima begitu saja: dari mana Git tahu commit mana yang lebih dulu, mengapa hash berubah total padahal isi berkasnya sama, dan apa bedanya penulis dengan pencatat. Chapter ini membuka satu commit sungguhan lalu membedahnya sampai ke lapisan berkasnya.
Membuka Isi Mentah Commit #
Kita siapkan repository kecil berisi dua commit — catatan rapat beserta arsipnya:
mkdir latihan-anatomi && cd latihan-anatomi
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf '# Catatan Rapat Tim\n\nRapat perdana: pembagian tugas.\n' > catatan-rapat.md
git add catatan-rapat.md
git commit -m "Tambah catatan rapat perdana"
printf '# Catatan Rapat Tim\n\nRapat perdana: pembagian tugas.\nRapat kedua: evaluasi sprint.\n' > catatan-rapat.md
cp catatan-rapat.md arsip-rapat.md
git add catatan-rapat.md arsip-rapat.md
git commit -m "Tambah hasil rapat kedua beserta arsipnya"Perintah git cat-file -p HEAD membuka isi objek commit terakhir apa adanya — bentuk mentah yang disimpan Git di dalam objects:
git cat-file -p HEADOutput yang Dihasilkan:
tree 5496b5f5f767e18ec339153e308a18f700a83128
parent 6d3cafe670b1c51a5c72c9caade9f24cc074ef1f
author Budi Santoso <[email protected]> 1791858600 +0700
committer Budi Santoso <[email protected]> 1791858600 +0700
Tambah hasil rapat kedua beserta arsipnyaLima baris di atas adalah seluruh isi sebuah commit. Mari kita bedah satu per satu:
tree 5496b5f...— penunjuk ke objek tree, yaitu daftar isi seluruh direktori pada saat commit dibuat: nama berkas apa saja ada dan hash isinya. Inilah snapshot yang dibekukan.parent 6d3cafe...— hash commit sebelumnya. Rantai rujukan parent inilah yang menyusun riwayat;git logmengikuti rantai ini dariHEADke belakang.author Budi Santoso <[email protected]> 1791858600 +0700— penulis asli perubahan: nama, surel, penanda waktu, dan zona waktunya.committer Budi Santoso <[email protected]> 1791858600 +0700— pihak yang mencatat commit ke riwayat, lengkap dengan penanda waktunya sendiri. Pada commit biasa author dan committer orang yang sama; keduanya berbeda ketika commit ditulis ulang lewat--amendatau dipindahkan lewatcherry-pickdanrebase.- Baris kosong lalu pesan — pesan commit disimpan apa adanya setelah satu baris kosong; judul dan body dipisahkan baris kosong tambahan di dalam pesan itu.
Commit Pertama Tidak Memiliki Parent #
Rantai parent harus berhenti di suatu tempat. Commit paling awal — root commit — tidak punya induk, dan objeknya memang tidak memuat baris parent. Kita buktikan pada commit pertama repository:
git cat-file -p HEAD~1Output yang Dihasilkan:
tree df476018aa83a35e8015402a5dcbb80931596b18
author Budi Santoso <[email protected]> 1791856800 +0700
committer Budi Santoso <[email protected]> 1791856800 +0700
Tambah catatan rapat perdanaBaris parent tidak ada: Git mencatat tree, author, committer, dan pesan, lalu berhenti. Label (root-commit) yang kita lihat pada keluaran commit pertama di section Dasar Repository
menandai persis kondisi ini. Branch baru selalu bertumpu pada commit yang sudah ada, jadi parent kosong hanya terjadi sekali per repository.
Penanda Waktu dan Zona Waktu #
Bagian 1791858600 +0700 pada baris author sering dianggap angka ajaib, padahal maknanya sederhana. Angka 1791858600 adalah Unix timestamp: jumlah detik sejak 1 Januari 1970 00:00:00 UTC — di sini menunjuk 13 Oktober 2026 pukul 02:30:00 UTC. Suku +0700 adalah offset zona waktu terhadap UTC: 02:30 UTC ditambah tujuh jam menjadi 09:30 WIB, persis waktu yang ditampilkan git log -1:
git log -1Output yang Dihasilkan:
commit 371d7dbd1774eadd03405efc62d80150fbd2692e
Author: Budi Santoso <[email protected]>
Date: Tue Oct 13 09:30:00 2026 +0700
Tambah hasil rapat kedua beserta arsipnyaGabungan timestamp dan offset membuat data waktu bebas ambigu: dua orang di zona berbeda yang commit pada saat yang sama menyimpan nilai UTC identik, dan git log merender waktunya dalam zona waktu masing-masing commit. Riwayat tetap terurut benar di mana pun repository di-clone.
Tiga Lapis Objek: commit, tree, blob #
Objek commit tidak menyimpan isi berkas secara langsung; commit hanya menunjuk tree. Tree berisi daftar berkas — dan tree itulah yang menunjuk blob, tempat isi berkas sesungguhnya disimpan. Kita turuni satu lapis dari commit terakhir:
git ls-tree HEADOutput yang Dihasilkan:
100644 blob 1440c501a615e9c7e8daae62671fb4146fe694b6 arsip-rapat.md
100644 blob 1440c501a615e9c7e8daae62671fb4146fe694b6 catatan-rapat.mdTiap baris memuat mode izin, tipe objek, hash, lalu nama berkas. Perhatikan keanehan yang disengaja: arsip-rapat.md dan catatan-rapat.md menunjuk blob yang sama — hash 1440c50... kembar identik — karena keduanya memang berisi byte yang persis sama. Isi blob itu bisa dibuka langsung dari commit:
git cat-file -p HEAD:catatan-rapat.mdOutput yang Dihasilkan:
# Catatan Rapat Tim
Rapat perdana: pembagian tugas.
Rapat kedua: evaluasi sprint.Karena setiap objek dinomori hash isinya, isi yang sama otomatis berbagi satu objek — tidak ada salinan ganda di database. Skema tiga lapisnya ringkas:
| Objek | Menyimpan | Dirujuk oleh |
|---|---|---|
commit | tree, parent, author, committer, pesan | branch, tag, parent commit lain |
tree | daftar nama berkas/subdirektori beserta hashnya | commit atau tree lain |
blob | isi mentah satu berkas | tree |
Hubungan ketiganya untuk repository kita tergambar berikut:
Commit terbaru 371d7db menunjuk tree 5496b5f yang memuat dua nama berkas dengan blob kembar 1440c50 — arsip berbagi objek dengan berkas aslinya. Commit induk 6d3cafe menunjuk tree lama df4760 berisi blob 9ea19da, versi awal catatan sebelum rapat kedua tercatat. Satu berkas berubah berarti satu blob baru dan satu tree baru, bukan seluruh isi disalin ulang. Bedah lengkap format tiap objek ada di section Internals dan Performa
.
Hash: Sidik Jari Seluruh Isi #
Hash commit dihitung dengan SHA-1 dari seluruh isi objeknya — tree, parent, identitas author dan committer beserta waktunya, sampai setiap byte pesan. Konsekuensinya dua arah: perubahan sekecil apa pun — satu spasi pada pesan, satu detik pada waktu, satu huruf pada satu berkas — menghasilkan hash yang sama sekali berbeda; sebaliknya, isi yang identik selalu menghasilkan hash yang sama, seperti blob kembar di atas, sehingga hash sekaligus menjadi alamat penyimpanan.
Bentuk penuh hash 40 karakter memang rewel untuk diketik, dan Git menyediakan singkatannya:
git rev-parse --short HEADOutput yang Dihasilkan:
371d7dbTujuh karakter — bentuk yang dipakai git log --oneline — praktis cukup karena ruang SHA-1 sangat luas; kemungkinan dua commit berawalan sama tujuh karakter nyaris nol. Bila mulai bentrok pada repository raksasa, Git otomatis memperpanjang singkatannya. Berbagai cara lain merujuk commit — HEAD~1, nama branch, rentang — dibahas tuntas di chapter Commit Hash dan References
.
Struktur ini menjelaskan satu hal terakhir: pesan commit ikut di-hash — pesan adalah bagian resmi dari identitas commit, bukan sekadar tempelan. Cara menulis pesan yang layak menjadi identitas itu adalah pokok bahasan chapter berikutnya: Menulis Commit Message .