Git'te Sildiğiniz Her Şeyi Geri Getirin: git reflog ile Kurtarma Rehberi
Yanlışlıkla git reset --hard yaptınız, bir dalı sildiniz ya da rebase her şeyi karıştırdı mı? Panik yapmayın: Git neredeyse hiçbir şeyi hemen silmez. git reflog ile kaybolan commit'leri, dalları ve stash'leri nasıl kurtaracağınızı anlatıyoruz.

İçindekiler 11
Saat gece yarısı. Üç günlük çalışmanızı bitirdiniz, "biraz temizlik yapayım" diyerek terminale bir komut yazdınız ve Enter'a bastınız:
git reset --hard HEAD~3
Bir saniye sonra fark ediyorsunuz: o üç commit, üç günlük işti. git log artık onları göstermiyor. Mide kasılması başlıyor.
İyi haber: işiniz büyük ihtimalle hâlâ orada. Git, commit'lenmiş hiçbir şeyi hemen silmez. Sadece ona giden yolu kaybettiniz. Bu yolu bulmanın adı git reflog.
Kısaca:
- Git,
HEAD'in ve dalların geçtiği her noktayı yerel bir günlükte (reflog) tutar. Varsayılan olarak bu kayıtlar 90 gün saklanır.git reflogile kaybolan commit'in kimliğini bulur,git resetya dagit branchile geri getirirsiniz.- Silinen dallar, bozulan rebase'ler ve hatalı merge'ler aynı yöntemle kurtarılır.
- Kurtarılamayan tek şey: hiç commit'lenmemiş değişiklikler. Sık commit atın.
Git neden hiçbir şeyi hemen silmez?
Git'te her commit, içeriğinden üretilen benzersiz bir kimlikle (hash) veritabanında saklanır. Dallar ve HEAD ise sadece bu commit'leri gösteren etiketlerdir. git reset --hard HEAD~3 yaptığınızda Git o üç commit'i silmez; dal etiketini üç adım geri taşır. Commit'ler yerinde durur, sadece hiçbir dal onları göstermediği için git log'da görünmezler.
Bu "sahipsiz" commit'ler, Git'in çöp toplayıcısı (git gc) onları temizleyene kadar yaşamaya devam eder. Varsayılan ayarlarda bu süre, reflog'da hâlâ bir kaydı olan commit'ler için 90 gün, olmayanlar için 30 gündür.
git reflog: Git'in kara kutusu
Uçakların kara kutusu gibi, reflog da deponuzda HEAD'in gittiği her yeri kaydeder: her commit, checkout, reset, rebase, merge ve pull.
git reflog
Çıktı şuna benzer:
a1b2c3d HEAD@{0}: reset: moving to HEAD~3
f9e8d7c HEAD@{1}: commit: Ödeme ekranı testleri eklendi
b4c5d6e HEAD@{2}: commit: Ödeme API entegrasyonu
e7f8a9b HEAD@{3}: commit: Sepet hesaplama düzeltmesi
a1b2c3d HEAD@{4}: checkout: moving from main to odeme-ozelligi
En üstteki satır, az önce yaptığınız felaket reset. Hemen altındaki HEAD@{1} ise reset'ten hemen önceki durum: üç günlük işinizin son commit'i.
Önemli bir not: reflog yereldir. Sadece sizin bilgisayarınızdaki depoda bulunur, uzak sunucuya gönderilmez. Başka birinin bilgisayarındaki ya da GitHub'daki bir durumu kendi reflog'unuzda göremezsiniz.
Senaryo 1: git reset --hard sonrası kaybolan commit'ler
Reset'ten önceki duruma dönmek için:
git reset --hard HEAD@{1}
Ya da doğrudan commit kimliğiyle:
git reset --hard f9e8d7c
Hepsi bu. git log üç commit'inizi tekrar gösterecek.
Daha temkinli olmak isterseniz, mevcut dalınıza dokunmadan önce kurtarılan noktadan yeni bir dal oluşturun ve orada inceleyin:
git branch kurtarma f9e8d7c
Pratik bir kısayol da var: reset, merge ve rebase gibi HEAD'i büyük ölçüde taşıyan komutlar, önceki konumu ORIG_HEAD adında özel bir referansa kaydeder. Hemen fark ettiyseniz git reset --hard ORIG_HEAD da aynı işi görür.
Senaryo 2: Yanlışlıkla silinen dal
git branch -D odeme-ozelligi
# Deleted branch odeme-ozelligi (was f9e8d7c).
Git, silerken dalın son commit'inin kimliğini zaten söylüyor. Terminal geçmişinde bu satırı görüyorsanız:
git branch odeme-ozelligi f9e8d7c
Terminal kapandıysa reflog'a dönün. O dala en son geçtiğiniz ya da orada commit attığınız satırları bulun:
git reflog | grep odeme-ozelligi
Çıkan commit kimliğiyle dalı yeniden oluşturun.
Senaryo 3: Karışan rebase
Bir rebase sırasında çakışmaları yanlış çözdünüz ve sonuç berbat oldu. Rebase henüz bitmediyse en kolay yol:
git rebase --abort
Rebase bittiyse reflog'da rebase başlamadan önceki satırı arayın. Genellikle "rebase (start)" satırının hemen altındaki kayıttır:
c3d4e5f HEAD@{5}: rebase (finish): returning to refs/heads/odeme-ozelligi
...
9a8b7c6 HEAD@{9}: rebase (start): checkout main
f9e8d7c HEAD@{10}: commit: Ödeme ekranı testleri eklendi
git reset --hard HEAD@{10}
Dal, rebase öncesindeki hâline döner.
Senaryo 4: Düşürülen stash
git stash drop ya da yanlışlıkla git stash clear yaptınız. Stash'ler de aslında commit'tir, ama normal reflog'da görünmezler. Onları bulmak için Git'in sahipsiz nesneleri tarayan aracını kullanın:
git fsck --unreachable | grep commit
Çıkan her commit kimliğinin içeriğine git show <kimlik> ile bakıp doğru stash'i bulduğunuzda:
git stash apply <kimlik>
Kurtarılamayanlar
Reflog güçlü ama sihirli değil. Şu durumlarda kurtarma zordur ya da imkânsızdır:
- Hiç commit'lenmemiş değişiklikler. Çalışma dizinindeki kaydedilmemiş değişiklikleri
git reset --hardya dagit checkout -- .ile silerseniz Git onları hiç kaydetmediği için geri getiremez. Tek istisna:git addile hazırlama alanına eklediğiniz dosyalar, Git veritabanına yazılmıştır vegit fsck --lost-foundile bulunabilir. Ama dosya adları kaybolur, içerikleri tek tek incelemeniz gerekir. - Çöp toplayıcının temizlediği commit'ler. Süre dolduktan ve
git gcçalıştıktan sonra geri dönüş yoktur. - Başka bir bilgisayardaki durum. Deponun yeni bir kopyasında (
git clone) reflog boştur.
Zorla push'un ezdiği uzak dal
Biri git push --force ile uzak daldaki commit'leri ezdiyse, çözüm genellikle o commit'lerin hâlâ bulunduğu bir yerel kopyadır: ezilen commit'leri daha önce çekmiş herhangi bir ekip arkadaşının deposu. O kişi kendi reflog'undan ya da dalından eski durumu bulup yeniden gönderebilir.
Bu kazayı önlemek için --force yerine şunu kullanın:
git push --force-with-lease
Bu seçenek, uzak dal sizin son bildiğiniz durumdan farklıysa, yani biri siz görmeden yeni bir commit gönderdiyse, push'u reddeder. Başkasının işini ezmenizi engeller.
İyi alışkanlıklar
- Sık ve küçük commit atın. Commit'lenmiş her şey kurtarılabilir. Bir işi bitirmeden de "WIP" commit'i atıp sonra düzenleyebilirsiniz.
- Tehlikeli işlemden önce yedek dal açın. Büyük bir rebase'den önce
git branch yedekdemek bir saniye sürer. --force-with-leasekullanın, çıplak--forcedeğil.- Paniklemeden önce
git reflogyazın. Kaybettiğinizi sandığınız şey büyük ihtimalle oradadır.
Sıkça sorulan sorular
git reflog ile git log arasındaki fark ne?
git log, bir daldan geriye doğru commit geçmişini gösterir; yalnızca o daldan ulaşılabilen commit'leri görür. git reflog ise HEAD'in yerel olarak geçtiği tüm noktaları, zaman sırasıyla gösterir; hiçbir dalın artık göstermediği commit'ler de dahil.
Reflog kayıtları ne kadar süre saklanır?
Varsayılan olarak, reflog kayıtları 90 gün, artık hiçbir daldan ulaşılamayan commit'lere ait kayıtlar ise 30 gün saklanır. Bu süreler gc.reflogExpire ve gc.reflogExpireUnreachable ayarlarıyla değiştirilebilir.
GitHub'da yaptığım bir hatayı reflog ile düzeltebilir miyim?
Kendi yerel deponuzda o commit'ler bir zamanlar varsa, evet: yerel reflog'dan bulup yeniden gönderebilirsiniz. Ama reflog uzak sunucudaki geçmişi tutmaz.
IDE'mdeki Git araçları reflog'u gösterir mi?
Birçok IDE ve Git arayüzü (ör. JetBrains IDE'lerindeki Git penceresi) reflog benzeri bir geçmiş ya da "yerel geçmiş" özelliği sunar. Ama en güvenilir ve evrensel yol, terminalde git reflog'dur.
Versiyon kontrolünü doğru kullanmak, bir yazılım ekibinin hem hızını hem de güvenliğini belirler. Git iş akışları, CI/CD süreçleri ve sağlam bir geliştirme altyapısıyla projelerinizi büyütmek isterseniz web uygulama geliştirme sayfamızdan bize ulaşabilirsiniz.


