Git'te değişiklik geri almanın tek bir yolu yoktur ve git reset revert ile git stash komutlarını birbirine karıştırmak, en sık yaşanan kafa karışıklıklarından biridir. Üçü de "geri al" hissi verir ama tamamen farklı işler yapar: biri değişikliği geçici kenara koyar, biri tarihi geriye sarar, biri ise geçmişi bozmadan tersine çeviren yeni bir commit üretir. Hangisini seçeceğini bilmek, bir akşam boyu kaybolan çalışma ile temiz bir geçmiş arasındaki farktır.
Üç komut, üç farklı amaç
Önce zihinsel modeli netleştirelim. Git'te üç alan vardır: çalışma dizini (working directory), indeks (staging area) ve commit geçmişi (HEAD). Komutların farkı, bu üç alandan hangisine dokunduklarıdır.
git stash— çalışma dizinindeki ve indeksdeki kaydedilmemiş değişiklikleri bir kenara koyar, dizini son commit'e döndürür. Hiçbir şey silinmez, sonra geri alabilirsin.git reset— HEAD'i (ve isteğe göre indeksi ve çalışma dizinini) başka bir commit'e taşır. Geçmişi yeniden yazar.git revert— bir commit'in etkisini tersine çeviren yeni bir commit oluşturur. Geçmiş aynen kalır, üstüne "iptal" eklenir.
git stash: yarım işi güvenle park etmek
Bir özellik üzerinde çalışırken aniden başka bir dala geçip acil bir hata düzeltmen gerekti, ama elindeki iş henüz commit edilecek olgunlukta değil. İşte git stash tam buradadır.
git stash push -m "yarım kalan filtre formu"
# dizin artık temiz, dalı değiştir, hotfix yap...
git stash list
git stash pop # son stash'i geri getir ve listeden sil
git stash apply # geri getir ama listede tut
Takip edilmeyen (untracked) dosyaları da saklamak için git stash -u kullan. Birden çok stash arasında dolaşırken git stash pop stash@{1} gibi indeks belirtebilirsin. Stash geçici bir cep gibidir: commit etmeden, dalı kirletmeden işini bir kenara alırsın. Kalıcı bir kayıt yöntemi değildir; günlerce stash'te iş tutmak yerine bir WIP commit açmak daha güvenlidir.
git reset: HEAD'i geriye sarmak
git reset en güçlü ve en yanlış anlaşılan komuttur. Üç modu, üç farklı sertlik seviyesidir:
--soft— sadece HEAD'i taşır. Değişiklikler indeksde durur, sanki yenidengit addyapmışsın gibi. Son birkaç commit'i tek bir commit'te toplamak için idealdir.--mixed(varsayılan) — HEAD'i taşır ve indeksi sıfırlar. Değişiklikler çalışma dizininde "unstaged" olarak kalır.--hard— HEAD'i, indeksi ve çalışma dizinini birden sıfırlar. Kaydedilmemiş her şey gider.
# Son 3 commit'i tek commit'te birleştir (mesajları kaybetmeden)
git reset --soft HEAD~3
git commit -m "filtre özelliği"
# Yanlışlıkla stage'lenen dosyayı geri al (içeriğe dokunmadan)
git reset HEAD dosya.php
# DİKKAT: çalışma dizinini son commit'e zorla döndür
git reset --hard HEAD
Altın kural: git reset'i yalnızca henüz paylaşmadığın (push etmediğin) commit'lerde kullan. Paylaşılmış bir dalda reset ile commit silip --force ile push edersen, aynı dalda çalışan herkesin geçmişi senin geçmişinden ayrılır.
git revert: paylaşılmış geçmişi güvenle geri almak
Hatalı bir commit zaten main'e gittiyse ve başkaları onu çektiyse, geçmişi silemezsin. git revert burada doğru araçtır: hatalı commit'in yaptığı her şeyi tersine çeviren yeni bir commit ekler.
# Belirli bir commit'i tersine çevir
git revert a1b2c3d
# Birleştirme (merge) commit'ini geri al — hangi ana hattı tutacağını belirt
git revert -m 1 <merge-sha>
# Commit oluşturmadan sadece değişikliği uygula
git revert --no-commit a1b2c3d
Revert geçmişi bozmaz, bu yüzden ekip çalışmasında ve üretim dallarında en güvenli seçenektir. Birinin görebildiği bir hata için tarihi yeniden yazmaya çalışmak yerine, dürüstçe "bu commit'i geri aldım" diyen bir kayıt bırakırsın.
Hangi durumda hangisi?
- Yarım işi kenara alıp dal değiştireceksin → stash
- Henüz push etmediğin commit'leri toplamak/düzeltmek → reset --soft veya
git commit --amend - Yanlış stage'lenmiş dosyayı staging'den çıkarmak → reset (mixed)
- Yerelde her şeyi son commit'e döndürmek → reset --hard (dikkatli ol)
- Paylaşılmış/push edilmiş bir commit'i geri almak → revert
Yanlışlıkla sildiysen: reflog kurtarır
git reset --hard ile kaybettiğini sandığın commit'ler genellikle hâlâ oradadır. Git, HEAD'in her hareketini reflog'da tutar:
git reflog
# çıktıda hedef commit'in sha'sını bul, sonra:
git reset --hard a1b2c3d
# ya da kayıp commit'i yeni bir dala al
git branch kurtarma a1b2c3d
Reflog girdileri varsayılan olarak 90 gün saklanır, bu yüzden panik yapmadan önce her zaman önce reflog'a bak.
Sık Sorulan Sorular
git reset --hard ile kaybettiğim dosyaları geri alabilir miyim?
Eğer kayıp değişiklik daha önce commit edildiyse evet: git reflog ile commit'i bul ve geri dön. Ama hiç commit edilmemiş, sadece çalışma dizininde duran değişiklikler --hard ile kalıcı olarak silinir; bunları reflog kurtaramaz.
Push ettikten sonra reset yapabilir miyim?
Teknik olarak --force ile evet, ama paylaşılan dallarda yapma. Başkaları o commit'leri çekmişse geçmiş çatallanır. Bunun yerine git revert kullan; aynı sonucu güvenle verir.
stash ile reset arasındaki temel fark nedir?
Stash değişiklikleri saklayıp sonra geri vermek içindir, geçmişe dokunmaz. Reset ise HEAD'i ve indeksi gerçekten geri taşır. Bir işi "sonra devam etmek üzere" park ediyorsan stash, geçmişi düzenliyorsan reset düşün.
Geri alma stratejini netleştirelim. Git akışın, sürüm yönetimin veya CI/CD hattın için sağlam bir kurulum mu istiyorsun? Benimle iletişime geç, projene uygun en güvenli iş akışını birlikte kuralım.