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:

bash
head -3 .git/logs/HEAD

Output yang Dihasilkan:

text
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 fitur

Setiap 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:

bash
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 reflog

Dua commit awal mengisi main, satu commit dibuat di branch fitur, lalu commit “Tambah salam dunia” sengaja dibuang dengan reset:

Output yang Dihasilkan:

text
HEAD is now at a787c38 Tambah salam pembuka

Keluaran git reflog — perintah pengintip di akhir blok — dicatat lengkap di bawah ini:

Output yang Dihasilkan:

text
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 proyek

Hash 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:

BagianContohArti
Hasha787c38Posisi HEAD setelah aksi berlangsung
Penunjuk posisiHEAD@{0}Nomor urut; 0 berarti posisi terkini, 1 posisi sebelumnya, dst.
AksiresetPerintah yang menggerakkan HEAD
Detailmoving to HEAD~1Tujuan 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 reflogDipicu oleh
commit (initial): Mulai catatan proyekCommit pertama repository
commit: Tambah salam pembukagit commit biasa
checkout: moving from main to fiturgit switch maupun git checkout
reset: moving to HEAD~1git 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>:

bash
git reflog show main

Output yang Dihasilkan:

text
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 proyek

Reflog 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:

bash
git reflog show fitur

Output yang Dihasilkan:

text
1e71357 fitur@{0}: commit: Catat langkah pertama
a787c38 fitur@{1}: branch: Created from HEAD

Baris 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:

bash
git rev-parse HEAD@{1}

Output yang Dihasilkan:

text
1045edc764519450bf232d7b25f1b4f6ad0e2be9

HEAD@{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:

bash
git log -g -3

Output yang Dihasilkan:

text
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 pembuka

Header 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 .