git reflog — yo'qolgan commitlarni tiklash

~15 daq · Git · Git Tarixini Boshqarish

Muammodan boshlaylik

Dahshatli daqiqalar:

  • git reset --hard HEAD~3 — va keyin tushundingiz, bu commitlar kerak edi
  • git branch -D feature/tolov — ikki haftalik ish, hali merge qilinmagan
  • Interaktiv rebase da adashib, drop qildingiz
  • git log da commitlar yo'q. Panika.

Yaxshi xabar: Git deyarli hech narsani unutmaydi. Commit qilingan narsa — yo'qolmagan. Uni topish vositasi — git reflog.


Reflog nima?

Reflog (reference log) — HEAD qayerda bo'lganining shaxsiy kundaligi. Har safar HEAD siljiganda — commit, checkout, reset, rebase, merge, pull — Git bir qator yozadi.

git reflog
a3f9c2b (HEAD -> main) HEAD@{0}: reset: moving to HEAD~3
f6a7b8c HEAD@{1}: commit: To'lov: webhook qo'shildi
e5f6a7b HEAD@{2}: commit: To'lov: Payme API
d4e5f6a HEAD@{3}: commit: To'lov modeli
a3f9c2b HEAD@{4}: checkout: moving from feature/savat to main
...

git log — branch tarixi (commitlar zanjiri). git reflog — sizning harakatlaringiz tarixi. Reset qilingan, branch i o'chirilgan commitlar log da ko'rinmaydi — lekin reflog da bor.

Yozuv Ma'nosi
HEAD@{0} Hozirgi holat
HEAD@{1} Bitta harakat oldin
HEAD@{2} Ikki harakat oldin

Tiklash holatlari

1. Xato reset --hard

git reflog
a3f9c2b HEAD@{0}: reset: moving to HEAD~3
f6a7b8c HEAD@{1}: commit: To'lov: webhook qo'shildi      ← reset dan oldingi holat
git reset --hard f6a7b8c           # yoki: git reset --hard HEAD@{1}

3 ta commit qaytdi.

2. O'chirilgan branch

git branch -D feature/tolov
# Deleted branch feature/tolov (was f6a7b8c).

Git o'chirishda oxirgi hash ni o'zi aytadi! Terminalda ko'rinmasa — reflog da qidiring:

git reflog | grep "feature/tolov"
f6a7b8c HEAD@{5}: checkout: moving from feature/tolov to main

Branch ni qayta yaratish:

git branch feature/tolov f6a7b8c

Branch va uning barcha commitlari qaytdi.

3. Rebase ni bekor qilish

Interaktiv rebase dan keyin hammasi buzildi:

git reflog
9a8b7c6 HEAD@{0}: rebase (finish): returning to refs/heads/feature/savat
...
c1d2e3f HEAD@{7}: rebase (start): checkout main
e5f6a7b HEAD@{8}: commit: Savat: miqdor tanlash      ← rebase dan oldin
git reset --hard HEAD@{8}

Yoki qulayroq — ORIG_HEAD: Git xavfli operatsiyalardan (reset, rebase, merge) oldin eski holatni shu yerda saqlaydi:

git reset --hard ORIG_HEAD

4. Amend dan oldingi commit

git reflog
# ... HEAD@{1}: commit: Asl commit
git show HEAD@{1}                  # amend dan oldingi versiya

Xavfsiz tiklash — avval ko'ring

reset --hard ga shoshilmang — avval topilgan commitni tekshiring:

git show f6a7b8c                    # nima bor?
git log --oneline f6a7b8c -5        # tarixi
git switch -c tiklash f6a7b8c       # alohida branch da xavfsiz o'rganish

Yangi branch yaratish — eng xavfsiz yo'l: hech narsa ustidan yozilmaydi, keyin xotirjam merge yoki cherry-pick qilasiz.


Vaqt bo'yicha

git reflog --date=relative
git reflog --date=iso
a3f9c2b HEAD@{2 minutes ago}: reset: moving to HEAD~3
f6a7b8c HEAD@{1 hour ago}: commit: To'lov: webhook qo'shildi
git switch --detach "main@{yesterday}"      # main kecha qayerda edi
git diff "main@{2.hours.ago}" main          # 2 soat ichida nima o'zgardi

Har bir branch ning o'z reflog i bor: git reflog show feature/savat.


Reflog ning chegaralari

[!WARNING] Reflog qutqara olmaydigan narsalar:

  • Hech qachon commit qilinmagan o'zgarishlar — reset --hard yoki restore bilan o'chirilgan ishchi papka o'zgarishlari. Git ularni hech qachon saqlamagan
  • Boshqa kompyuterdagi harakatlar — reflog lokal, push qilinmaydi
  • Juda eski yozuvlar — standart holatda 90 kun (yetib bo'lmaydigan commitlar uchun — 30 kun), keyin git gc tozalaydi

Shundan muhim xulosa: tez-tez commit qiling. Commit qilingan narsa — reflog bilan himoyalangan. Hatto "WIP" commit ham — saqlanish nuqtasi.

Staging ga qo'shilgan (git add), lekin commit qilinmagan fayllar uchun oxirgi chora bor — Git ularni blob sifatida saqlagan:

git fsck --lost-found

.git/lost-found/other/ da nomsiz fayllar paydo bo'ladi — ularni birma-bir ochib, kerakligini topish mumkin. Qiyin, lekin ba'zan qutqaradi.


Nima uchun shunday?

Nima uchun Git "o'chirilgan" commitlarni darhol o'chirmaydi?

Chunki Git ning ma'lumotlar modeli — qo'shish asosida: commitlar, fayllar, papkalar — o'zgarmas obyektlar sifatida .git/objects ga yoziladi va hech qachon joyida o'zgartirilmaydi (26-dars). "Reset", "branch o'chirish", "rebase" — faqat ko'rsatkichlarni siljitadi; obyektlar joyida qoladi. Ular faqat hech narsa ishora qilmasa va ma'lum muddat o'tgandan keyingina axlat yig'uvchi (gc) tomonidan tozalanadi. Reflog esa — yaqinda ishora qilingan barcha joylarning ro'yxati. Natija: Git da "qaytarib bo'lmaydigan xato" deyarli yo'q — faqat "qaerda ekanini bilmaslik" bor. Bu bilim Git dan qo'rqmaslikka yordam beradi.


Xulosa

Eslab qoling:

  • git reflog — HEAD harakatlari kundaligi (lokal, ~90 kun)
  • git log — branch tarixi; git reflog — sizning harakatlaringiz
  • HEAD@{N} — N harakat oldingi holat; ORIG_HEAD — xavfli operatsiyadan oldingi
  • Xato reset: git reset --hard HEAD@{1}
  • O'chirilgan branch: git branch nom <hash>
  • Avval ko'ring: git show, git switch -c tiklash <hash>
  • Commit qilinmaganlarni qutqarmaydi — tez-tez commit qiling
  • Oxirgi chora: git fsck --lost-found

Keyingi bo'lim

6-bo'lim: Professional Git Workflow — Gitflow, GitHub Flow, Conventional Commits, SemVer va teglar.