Chapter-chapter sebelumnya sudah menunjukkan betapa mudahnya penunjuk berpindah di Git: reset
menggeser branch, rebase
menulis ulang commit, dan branch bisa dihapus dengan satu perintah. Masalahnya, keputusan seperti itu kadang diambil terburu-buru — dan tiba-tiba commit yang kita butuhkan tidak lagi muncul di git log. Kabar baiknya: Git diam-diam mencatat setiap pergerakan HEAD dan setiap branch di sebuah log internal bernama reflog. Chapter ini membuka log itu, membedah formatnya baris demi baris, dan menunjukkan bahwa tidak ada satu pun aksi — commit, reset, atau berpindah branch — yang luput dari pencatatan.
Reflog Adalah Catatan Lokal, Bukan Riwayat Bersama #
Reflog (reference log) adalah daftar pergerakan yang disimpan Git setiap kali sebuah referensi berpindah: HEAD pindah karena git switch, branch maju karena git commit, atau mundur karena git reset. Daftar itu ditulis sebagai berkas biasa di dalam .git/logs/ — kita bisa membacanya langsung:
head -3 .git/logs/HEADOutput yang Dihasilkan:
0000000000000000000000000000000000000000 b4484eb9c2d132d06da3a6c7d2009d9e8b68e8a7 Budi Santoso <[email protected]> 1792548000 +0700 commit (initial): Mulai catatan proyek
b4484eb9c2d132d06da3a6c7d2009d9e8b68e8a7 a787c389b5a5d5d1cd615800d2505ca150ee5603 Budi Santoso <[email protected]> 1792548600 +0700 commit: Tambah salam pembuka
a787c389b5a5d5d1cd615800d2505ca150ee5603 a787c389b5a5d5d1cd615800d2505ca150ee5603 Budi Santoso <[email protected]> 1792548900 +0700 checkout: moving from main to fiturSetiap baris berisi hash posisi lama, hash posisi baru, identitas pelaku, penanda waktu, lalu — setelah sebuah TAB — pesan aksinya. Perintah git reflog nanti akan memformat daftar mentah ini menjadi tabel yang jauh lebih mudah dibaca.
Membangun Skenario: commit, switch, dan reset #
Kita bangun repository latihan yang mengalami tiga jenis aksi — commit, berpindah branch, dan reset — supaya reflog-nya beraneka:
mkdir latihan-reflog && cd latihan-reflog
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf '# Catatan\n' > catatan.md
git add catatan.md
git commit -m "Mulai catatan proyek"
printf '# Catatan\nhalo\n' > catatan.md
git add catatan.md
git commit -m "Tambah salam pembuka"
git switch -c fitur
printf 'langkah 1\n' > langkah.md
git add langkah.md
git commit -m "Catat langkah pertama"
git switch main
printf '# Catatan\nhalo\ndunia\n' > catatan.md
git add catatan.md
git commit -m "Tambah salam dunia"
git reset --hard HEAD~1
git reflogDua commit awal mengisi main, satu commit dibuat di branch fitur, lalu commit “Tambah salam dunia” sengaja dibuang dengan reset:
Output yang Dihasilkan:
HEAD is now at a787c38 Tambah salam pembukaKeluaran git reflog — perintah pengintip di akhir blok — dicatat lengkap di bawah ini:
Output yang Dihasilkan:
a787c38 HEAD@{0}: reset: moving to HEAD~1
1045edc HEAD@{1}: commit: Tambah salam dunia
a787c38 HEAD@{2}: checkout: moving from fitur to main
1e71357 HEAD@{3}: commit: Catat langkah pertama
a787c38 HEAD@{4}: checkout: moving from main to fitur
a787c38 HEAD@{5}: commit: Tambah salam pembuka
b4484eb HEAD@{6}: commit (initial): Mulai catatan proyekHash pada keluaran di atas milik mesin uji dan akan berbeda di mesin pembaca; yang tetap sama adalah pola setiap kolomnya.
Membedah Satu Baris reflog #
Format setiap baris konsisten: <hash> HEAD@{<nomor>}: <aksi>: <detail>. Tabel berikut membedah baris teratas:
| Bagian | Contoh | Arti |
|---|---|---|
| Hash | a787c38 | Posisi HEAD setelah aksi berlangsung |
| Penunjuk posisi | HEAD@{0} | Nomor urut; 0 berarti posisi terkini, 1 posisi sebelumnya, dst. |
| Aksi | reset | Perintah yang menggerakkan HEAD |
| Detail | moving to HEAD~1 | Tujuan atau keterangan tambahan aksi |
Tiga kolom pertama paling penting saat pemulihan: hash menunjukkan di mana HEAD pernah berada, dan HEAD@{n} memberi cara singkat menyebut posisi itu tanpa menyalin hash. Jenis pesan yang muncul pada skenario kita selengkapnya:
| Pesan reflog | Dipicu oleh |
|---|---|
commit (initial): Mulai catatan proyek | Commit pertama repository |
commit: Tambah salam pembuka | git commit biasa |
checkout: moving from main to fitur | git switch maupun git checkout |
reset: moving to HEAD~1 | git reset --hard |
Perhatikan pula urutan baris: entri paling baru berada paling atas. Baris 1045edc HEAD@{1}: commit: Tambah salam dunia adalah bukti tertulis bahwa commit “hilang” akibat reset barusan pernah ada — inilah yang kita kejar di seluruh section ini.
Reflog per Branch #
git reflog menampilkan reflog HEAD saja. Setiap branch juga punya reflog sendiri, diakses dengan git reflog show <branch>:
git reflog show mainOutput yang Dihasilkan:
a787c38 main@{0}: reset: moving to HEAD~1
1045edc main@{1}: commit: Tambah salam dunia
a787c38 main@{2}: commit: Tambah salam pembuka
b4484eb main@{3}: commit (initial): Mulai catatan proyekReflog main hanya mencatat pergerakan yang menggerakkan main itu sendiri — tiga commit dan satu reset; perpindahan ke fitur tidak masuk karena main diam di tempat. Sebaliknya, reflog fitur menceritakan kisahnya:
git reflog show fiturOutput yang Dihasilkan:
1e71357 fitur@{0}: commit: Catat langkah pertama
a787c38 fitur@{1}: branch: Created from HEADBaris branch: Created from HEAD dicatat otomatis saat branch dibuat. Dua tampilan ini saling melengkapi: saat sebuah branch terhapus, reflog HEAD tetap menyimpan jejak commit-commitnya — pembahasan penuhnya menempati chapter Memulihkan Branch Terhapus
.
Menyebut Posisi Lama dengan HEAD@{n} #
Sintaks HEAD@{n} bukan sekadar label tampilan — Git menerimanya sebagai alamat commit di mana pun hash diterima:
git rev-parse HEAD@{1}Output yang Dihasilkan:
1045edc764519450bf232d7b25f1b4f6ad0e2be9HEAD@{1} terurai menjadi hash penuh commit “Tambah salam dunia” — commit yang barusan dibuang reset. Perintah seperti git branch pulihan HEAD@{1} atau git reset --hard HEAD@{1} kini bisa kita jalankan tanpa pernah menyalin satu hash pun secara manual.
Menelusuri reflog dengan git log -g #
git log -g menampilkan isi reflog dalam format git log yang sudah familier — lengkap dengan penulis dan tanggal commit:
git log -g -3Output yang Dihasilkan:
commit a787c389b5a5d5d1cd615800d2505ca150ee5603
Reflog: HEAD@{0} (Budi Santoso <[email protected]>)
Reflog message: reset: moving to HEAD~1
Author: Budi Santoso <[email protected]>
Date: Wed Oct 21 09:10:00 2026 +0700
Tambah salam pembuka
commit 1045edc764519450bf232d7b25f1b4f6ad0e2be9
Reflog: HEAD@{1} (Budi Santoso <[email protected]>)
Reflog message: commit: Tambah salam dunia
Author: Budi Santoso <[email protected]>
Date: Wed Oct 21 09:30:00 2026 +0700
Tambah salam dunia
commit a787c389b5a5d5d1cd615800d2505ca150ee5603
Reflog: HEAD@{2} (Budi Santoso <[email protected]>)
Reflog message: checkout: moving from fitur to main
Author: Budi Santoso <[email protected]>
Date: Wed Oct 21 09:10:00 2026 +0700
Tambah salam pembukaHeader Reflog: HEAD@{n} dan Reflog message: ... menandai bahwa urutan commit diambil dari reflog, bukan dari rantai parent. Perintah ini pas saat isi atau pesan lengkap commit lama ingin diperiksa — opsi git log biasa seperti -p tetap bisa digabungkan.
Masa Hidup Reflog #
Reflog tidak disimpan selamanya. Dua pengaturan mengatur pembersihannya: gc.reflogExpire untuk entri yang masih terjangkau (default 90 hari) dan gc.reflogExpireUnreachable untuk entri yang commit-nya sudah tidak dirujuk branch mana pun (default 30 hari). Saat git gc berjalan, entri yang melewati umur tersebut dihapus, dan commit yang kehilangan jejak terakhirnya menjadi kandidat pembersihan. Selama reflog masih memuat sebuah commit, commit itu aman — berapa kali pun riwayatnya ditulis ulang.
Diagram berikut merangkum hubungan sebab-akibat yang barusan kita amati:
Setiap aksi melahirkan satu entri; tidak ada aksi yang lolos. Dokumentasi resmi untuk seluruh sintaks reflog tersedia di git-reflog
. Dengan peta tangan ini, kita siap memulihkan benda pertama yang biasanya “hilang”: commit yang tertelan reset --hard — lanjut ke Memulihkan Commit
.