git reflog adalah catatan setiap kali HEAD berpindah di laptopmu: tiap commit, pindah branch, reset, atau merge. Commit yang "hilang" dari git log biasanya masih ada, dan reflog memberi tahu hash-nya. Mirip riwayat lokasi di Google Maps: walau kamu lupa lewat jalan mana, HP-mu mencatat setiap tempat yang pernah kamu datangi, jadi kamu bisa kembali ke sana.
🧪 Tebakan cepat: setelah
git reset --hard HEAD~1, apakahHEAD~1danHEAD@{1}menunjuk commit yang sama? Tebak dulu, jawabannya ada di bagian "HEAD~1beda denganHEAD@{1}".
Commit yang "hilang"
Ini kejadiannya. Repo baru dengan satu file, app.js:
git init
git add .
git commit -m "awal"
echo added >> app.js
git add .
git commit -m "fitur penting"
git reset --hard HEAD~1 # ups, salah perintah
$ git log --oneline
9a8b7c6 (HEAD -> main) awal
fitur penting gak muncul lagi, karena git log cuma menampilkan commit yang bisa dicapai dari branch. Tapi commit-nya belum dihapus. Git masih menyimpannya, cuma gak ada branch yang menunjuk ke sana. Hash di sini dan di Lab sama, di laptopmu nanti beda.
Membaca git reflog
$ git reflog
9a8b7c6 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~1
3d4e5f6 HEAD@{1}: commit: fitur penting
9a8b7c6 (HEAD -> main) HEAD@{2}: commit (initial): awal
- Satu baris untuk satu kali HEAD berpindah. Yang paling baru di atas.
HEAD@{0}adalah posisi sekarang,HEAD@{1}posisi satu perpindahan sebelumnya,HEAD@{2}dua perpindahan sebelumnya, dan seterusnya.- Sesudah titik dua ada jenis perpindahannya:
commit (initial)untuk commit pertama,commit,reset: moving to HEAD~1,checkout: moving from main to fitur(juga untukgit switch), ataumerge fitur. - Hash di depan adalah tempat HEAD berada setelah perpindahan itu. Jadi
3d4e5f6adalah commitfitur pentingyang dicari. (HEAD -> main)menandai baris yang hash-nya sama dengan posisimainsekarang.
Memulihkan dengan HEAD@{1}
$ git reset --hard HEAD@{1}
HEAD is now at 3d4e5f6 fitur penting
$ git log --oneline
3d4e5f6 (HEAD -> main) fitur penting
9a8b7c6 awal
HEAD@{1}bisa dipakai di mana pun Git minta commit, sama seperti hash.git reset --hard 3d4e5f6hasilnya sama.--hardaman di sini karena gak ada perubahan yang belum di-commit. Kalau ada, commit atau stash dulu.- Pemulihan ini juga perpindahan HEAD, jadi reflog dapat baris baru:
3d4e5f6 HEAD@{0}: reset: moving to HEAD@{1}. Semua nomor lama bergeser satu.
Branch yang terhapus
Branch eksperimen berisi commit 7c1d2e9 coba diskon yang belum di-merge, lalu terhapus:
$ git branch -D eksperimen
Deleted branch eksperimen (was 7c1d2e9).
Branch cuma nama yang menunjuk commit, jadi yang hilang cuma namanya. Hash-nya ada di pesan tadi, dan di reflog: 7c1d2e9 HEAD@{1}: commit: coba diskon. Bikin lagi namanya di commit itu:
git branch eksperimen 7c1d2e9 # branch baru bernama eksperimen, di commit 7c1d2e9
HEAD~1 beda dengan HEAD@{1}
| Tulisan | Artinya | Setelah reset --hard HEAD~1 tadi |
|---|---|---|
HEAD~1 |
satu commit sebelum HEAD di history (parent-nya) | gak ada, karena awal commit pertama |
HEAD@{1} |
posisi HEAD satu perpindahan sebelumnya | 3d4e5f6 fitur penting |
Itu jawaban tebakannya: beda. ~ mundur di history, @{} mundur di waktu. Untuk memulihkan, yang dipakai HEAD@{1}. git reset --hard HEAD~1 lagi malah memundurkan branch lebih jauh.
Berapa lama reflog disimpan
- Reflog lokal: cuma ada di laptopmu. Gak ikut
git push, dan clone baru mulai dengan reflog kosong. - Entri reflog disimpan 90 hari (default
gc.reflogExpire). Untuk commit yang sudah gak dicapai branch mana pun, sepertifitur pentingtadi, batasnya lebih pendek: 30 hari (gc.reflogExpireUnreachable). Setelah itugit gcboleh membuang commit-nya. - Reflog cuma mencatat commit. Perubahan yang belum pernah di-commit, lalu dibuang
git reset --hard, gak bisa diselamatkan reflog.
⚠️ Jebakan yang sering ketemu
- Nomor
HEAD@{n}bergeser. Tiap HEAD pindah, semua nomor bertambah satu. Bacagit reflogtepat sebelum memakainya, atau pakai hash-nya langsung. - Memulihkan dengan
HEAD~1. Itu mundur lagi di history, bukan kembali ke posisi tadi. - Menganggap reflog sebagai backup. Dia lokal dan punya masa kedaluwarsa. Pekerjaan penting di-push ke remote atau ditandai dengan tag.
- Pekerjaan yang belum di-commit. Sebelum
reset --hard, cekgit status. Yang belum pernah di-commit gak tercatat di reflog.
TL;DR: git reflog mencatat setiap perpindahan HEAD di laptopmu, terbaru HEAD@{0}. Commit yang hilang dari git log setelah reset --hard masih ada: cari di reflog, lalu git reset --hard HEAD@{1} atau git reset --hard <hash>. Branch yang terhapus dikembalikan dengan git branch <nama> <hash>. HEAD~1 itu parent di history, HEAD@{1} posisi HEAD sebelumnya. Reflog lokal, entrinya disimpan 90 hari (30 hari untuk commit yang sudah gak dicapai branch), dan gak bisa menyelamatkan perubahan yang belum pernah di-commit.