Geri Alma İşlemleri
Giriş: Neden Geri Alma Bu Kadar Önemli?
Yazılım geliştirirken hata yapmak kaçınılmaz. Yanlış dosyayı değiştirirsin, hatalı bir commit atarsın, bir özelliği geri almak istersin. Git'in en büyük vaatlerinden biri de bu: her zaman geri dönebilirsin.
Ama Git'te geri almanın birden fazla yolu var ve hangisini ne zaman kullanacağını bilmek kritik. Yanlış geri alma komutu, durumu daha da karmaşık hale getirebilir.
Bu derste Git'in üç geri alma aracını öğreneceğiz:
git restore— dosya düzeyinde geri almagit reset— commit düzeyinde geri alma (tehlikeli olabilir!)git revert— güvenli geri alma (yeni commit ile)
Her birinin ne zaman kullanılacağını, risklerini ve aralarındaki farkları netleştireceğiz.
🎬 Analoji: Word Belgesinde Geri Alma
Bir Word belgesinde çalışırken:
Ctrl+Z (Undo): Son yaptığını geri al →
git restoreBelgenin eski bir versiyonuna dön: "Bu versiyonu geri yükle" →
git resetDeğişikliği tersine çevir ama geçmişi koru: "Yaptığım değişikliğin tersini uygula" →
git revert
Ama Git'teki farklılık şu: Word'de Ctrl+Z basit, Git'te ise geri almanın kapsamı ve etkisi farklı.
Geri Alma Spektrumu:
GÜVENLİ ◄────────────────────────────────► TEHLİKELİ
git restore git revert git reset git reset
(dosya geri (yeni commit --soft --hard
al) ile geri al) (commit geri, (her şey
dosyalar kaybolur)
staging'de) git restore — Dosya Düzeyinde Geri Alma
git restore Git 2.23'te eklendi. Dosyaları önceki durumlarına geri yüklemek için kullanılır. En güvenli geri alma aracı.
Senaryo 1: Değişiklikleri Geri Al (Working Directory)
Bir dosyada değişiklik yaptın ama beğenmedin. Son commit'teki haline geri dönmek istiyorsun:
# style.css'de değişiklik yaptın
$ echo "h1 { color: red; font-size: 100px; }" >> style.css
$ git status
Changes not staged for commit:
modified: style.css
# Değişikliği geri al — son commit'teki haline dön
$ git restore style.css
$ git status
nothing to commit, working tree clean
# style.css son commit'teki haline geri döndüBirden fazla dosya:
# Tüm değişiklikleri geri al
$ git restore .
# Belirli dosyaları geri al
$ git restore style.css app.js⚠️ Dikkat:
git restoreile geri alınan değişiklikler kalıcı olarak kaybolur. Commit'lenmemiş değişiklikler Git'in kayıt sistemi dışındadır — geri getirmenin yolu yoktur. Bu komutu kullanmadan önce gerçekten geri almak istediğinden emin ol.
Senaryo 2: Staging'den Çıkarma
Bir dosyayı yanlışlıkla git add ile staging'e aldın:
# Yanlışlıkla tüm dosyaları staging'e aldın
$ git add .
$ git status
Changes to be committed:
modified: index.html
modified: style.css ← Bunu staging'den çıkarmak istiyorsun
# Staging'den çıkar (dosya değişikliği korunur)
$ git restore --staged style.css
$ git status
Changes to be committed:
modified: index.html
Changes not staged for commit:
modified: style.css ← Değişiklik duruyor, sadece staging'den çıktı--staged bayrağı ile dosyayı staging'den çıkarırsın ama dosyadaki değişiklik korunur. Sadece "commit'e dahil etme" demeksin.
Senaryo 3: Belirli Bir Commit'ten Dosya Geri Yükleme
# 3 commit önceki index.html'i geri yükle
$ git restore --source HEAD~3 index.html
# Belirli bir commit'ten geri yükle
$ git restore --source a1b2c3d style.css
$ git status
Changes not staged for commit:
modified: index.html
modified: style.css
# Dosyalar working directory'de değişti (staging'de değil)--source ile herhangi bir commit'teki dosya versiyonunu working directory'ye getirebilirsin.
restore Komut Haritası
# Working directory → son commit'e geri al
git restore dosya.txt
# Staging → unstage (dosya değişikliği korunur)
git restore --staged dosya.txt
# Hem staging'den çıkar hem değişikliği geri al
git restore --staged --worktree dosya.txt
# Belirli commit'ten geri yükle
git restore --source=HEAD~3 dosya.txt
# Tüm dosyaları geri al
git restore .
# Tüm dosyaları staging'den çıkar
git restore --staged .git reset — Commit Düzeyinde Geri Alma
git reset daha güçlü ama daha tehlikeli bir araç. Commit geçmişini yeniden yazar. Üç modu var ve her biri farklı kapsamda çalışır.
Üç Modu Anlamak
Working Dir Staging Commit History
─────────── ─────── ──────────────
git reset --soft ✅ ✅ ❌ Geri alır
git reset --mixed ✅ ❌ ❌ Geri alır (varsayılan)
git reset --hard ❌ ❌ ❌ Geri alır
✅ = Korunur (dokunulmaz)
❌ = Geri alınır / sıfırlanırDaha görsel bir şekilde:
Başlangıç durumu:
[Commit A] ← [Commit B] ← [Commit C] HEAD → main → C
Working Directory: C + değişiklikler
Staging Area: değişiklikler stage'de--soft: Sadece Commit'i Geri Al
$ git reset --soft HEAD~1Sonuç:
[Commit A] ← [Commit B] HEAD → main → B
Working Directory: C'nin içeriği + kendi değişikliklerin (korundu)
Staging Area: C'nin değişiklikleri burada (commit'e hazır)
C commit'i gitti ama içeriği staging'de bekliyor.Ne zaman kullanılır?
Son commit'in mesajını veya içeriğini tamamen değiştirmek istiyorsun
Birden fazla commit'i tek bir commit'te birleştirmek istiyorsun (squash)
# Son 3 commit'i tek commit'te birleştir
$ git reset --soft HEAD~3
# Artık 3 commit'in tüm değişiklikleri staging'de
$ git commit -m "feat: Tüm login özelliği tamamlandı"--mixed (Varsayılan): Commit ve Staging'i Geri Al
$ git reset HEAD~1
# veya açıkça:
$ git reset --mixed HEAD~1Sonuç:
[Commit A] ← [Commit B] HEAD → main → B
Working Directory: C'nin değişiklikleri hâlâ dosyalarda (korundu)
Staging Area: BOŞ (sıfırlandı)
C commit'i gitti, staging temizlendi, ama dosya değişiklikleri duruyor.Ne zaman kullanılır?
Commit'i geri almak ama değişiklikleri kaybetmemek istiyorsun
Değişiklikleri yeniden düzenleyip farklı commit'ler oluşturmak istiyorsun
# Son commit'i geri al, değişiklikleri yeniden düzenle
$ git reset HEAD~1
$ git status
Changes not staged for commit:
modified: login.js
modified: auth.js
modified: style.css
# Şimdi bunları farklı commit'lere ayır
$ git add login.js auth.js
$ git commit -m "feat: Login sistemi"
$ git add style.css
$ git commit -m "style: Login sayfası stilleri"--hard: Her Şeyi Geri Al (Tehlikeli!)
$ git reset --hard HEAD~1Sonuç:
[Commit A] ← [Commit B] HEAD → main → B
Working Directory: B'nin durumuna geri döndü (DEĞİŞİKLİKLER SİLİNDİ!)
Staging Area: BOŞ
C commit'i gitti. C'nin değişiklikleri gitti.
Commit'lenmemiş değişiklikler de gitti.
HER ŞEY GİTTİ.⚠️ Dikkat:
git reset --harden tehlikeli Git komutlarından biridir. Commit'lenmemiş değişiklikler geri getirilemez. Commit'lenmiş değişikliklerreflogile kurtarılabilir ama commit'lenmemiş olanlar kayıp. Bu komutu kullanmadan önce iki kere düşün.
Ne zaman kullanılır?
Yerel değişikliklerini tamamen çöpe atmak istiyorsun
Projeyi bilinen iyi bir duruma geri getirmek istiyorsun
"Her şeyi sil, baştan başla" dediğin an
# SON ÇARE: Her şeyi son commit'e geri al
$ git reset --hard HEAD
# Veya belirli bir commit'e geri dön
$ git reset --hard a1b2c3dReset Karşılaştırma Tablosu
┌─────────────────┬──────────┬──────────┬──────────────┐
│ Mod │ Working │ Staging │ Commit │
│ │ Dir │ Area │ History │
├─────────────────┼──────────┼──────────┼──────────────┤
│ --soft │ Korunur │ Korunur │ Geri alınır │
│ --mixed (def.) │ Korunur │ Sıfırlar │ Geri alınır │
│ --hard │ Sıfırlar │ Sıfırlar │ Geri alınır │
└─────────────────┴──────────┴──────────┴──────────────┘Reset ile Belirli Dosyayı Unstage Etmek
git reset ayrıca tek bir dosyayı staging'den çıkarmak için de kullanılır:
# Bu ikisi aynı şeyi yapar:
$ git reset HEAD dosya.txt
$ git restore --staged dosya.txtModern Git'te git restore --staged tercih ediliyor çünkü niyeti daha açık ifade ediyor.
git revert — Güvenli Geri Alma
git revert, bir commit'in değişikliklerini tersine çeviren yeni bir commit oluşturur. Geçmişi yeniden yazmaz — üzerine ekler.
Nasıl Çalışır?
Öncesi:
[A] ← [B] ← [C] ← [D] HEAD → main → D
$ git revert C
Sonrası:
[A] ← [B] ← [C] ← [D] ← [C'] HEAD → main → C'
C' = C'nin tersini uygulayan yeni commit
C hâlâ geçmişte var. Geçmiş değişmedi.
D'nin değişiklikleri de korundu.
Sadece C'nin eklediği şeyler geri alındı.Pratik Kullanım
# Son commit'i geri al
$ git revert HEAD
# Editör açılır, revert commit mesajını düzenle
# Varsayılan mesaj: "Revert 'feat: İletişim formu eklendi'"
[main e6f7g8h] Revert "feat: İletişim formu eklendi"
2 files changed, 0 insertions(+), 25 deletions(-)
# Mesajı kendim yazayım
$ git revert HEAD --no-edit
# Varsayılan mesajı kabul et, editör açılmasın
# Belirli bir commit'i geri al
$ git revert a1b2c3d
# Log'a bak
$ git log --oneline
e6f7g8h (HEAD -> main) Revert "feat: İletişim formu eklendi"
d4e5f6g feat: İletişim formu eklendi
a1b2c3d feat: Hakkımda sayfası
h7i8j9k feat: Proje başlatıldıBirden Fazla Commit'i Revert Etmek
# Son 3 commit'i tek tek revert et (en sondan başla)
$ git revert HEAD~2..HEAD
# veya
$ git revert HEAD HEAD~1 HEAD~2
# Commit yapmadan sadece dosyaları değiştir (birden fazla revert'i birleştirmek için)
$ git revert --no-commit HEAD~2..HEAD
$ git commit -m "revert: Son 3 commit geri alındı"💡 İpucu: Revert sırasında conflict çıkabilir — özellikle geri alınan commit'ten sonra aynı dosyalarda başka değişiklikler yapıldıysa. Conflict çözümünü ileriki derslerde öğreneceğiz.
Revert vs Reset: Ne Zaman Hangisi?
Bu en çok sorulan sorulardan biri. Basit kural:
┌──────────────────────────────────────────────────────────────┐
│ │
│ Commit'i PUSH ETTİN Mİ? │
│ │
│ HAYIR (sadece yerel) ──────► git reset kullanabilirsin │
│ (geçmişi yeniden yaz, temiz) │
│ │
│ EVET (başkaları gördü) ────► git revert kullan │
│ (geçmişi koru, yeni commit) │
│ │
└──────────────────────────────────────────────────────────────┘Neden push'landıktan sonra reset kullanmıyoruz?
Çünkü Ali ve Ayşe senin commit'ini çoktan pull etmiş olabilir. Sen geçmişi yeniden yazarsan, onların geçmişiyle senin geçmişin uyumsuz hale gelir. Karmaşa çıkar.
Revert ise yeni bir commit olduğu için herkesin geçmişiyle uyumlu kalır.
Reset ile:
Ali: [A] ← [B] ← [C] ← [D]
Sen: [A] ← [B] ← [C] ← D'yi sildim!
Ayşe: [A] ← [B] ← [C] ← [D]
→ Uyumsuzluk! Ali ve Ayşe'nin D'si var, senin yok.
Revert ile:
Ali: [A] ← [B] ← [C] ← [D]
Sen: [A] ← [B] ← [C] ← [D] ← [D'] ← D'nin tersini ekledim
Ayşe: [A] ← [B] ← [C] ← [D]
→ Ayşe pull edince D' gelir, sorunsuz.Kurtarma: git reflog — Son Çare
git reset --hard yaptın ve commit'lerin kayboldu? Panik yapma. reflog hayat kurtarır.
Reflog, HEAD'in son 30 gündeki tüm hareketlerini kaydeder:
$ git reflog
e6f7g8h (HEAD -> main) HEAD@{0}: reset: moving to HEAD~2
d4e5f6g HEAD@{1}: commit: feat: İletişim formu eklendi
a1b2c3d HEAD@{2}: commit: feat: Hakkımda sayfası
h7i8j9k HEAD@{3}: commit (initial): feat: Proje başlatıldıKayıp commit'i gördün mü? d4e5f6g! Geri getirelim:
# O commit'e geri dön
$ git reset --hard d4e5f6g
HEAD is now at d4e5f6g feat: İletişim formu eklendi
# Veya yeni bir branch olarak kurtarma
$ git branch kurtarma d4e5f6g💡 İpucu: Reflog sadece yerel repo'da çalışır ve sadece commit'lenmiş değişiklikleri kurtarabilir.
git addbile yapmadığın değişiklikler kaybolursa, reflog bile kurtaramaz. Sık commit at — güvenlik ağın olsun.
Karşılaştırma: Tüm Geri Alma Yöntemleri
┌───────────────────┬──────────────┬──────────────┬───────────────┐
│ Yöntem │ Ne yapar? │ Güvenli mi? │ Ne zaman? │
├───────────────────┼──────────────┼──────────────┼───────────────┤
│ git restore │ Dosyayı geri │ ⚠️ Commit- │ Dosya düzeyi │
│ │ al │ lenmemiş │ geri alma │
│ │ │ kaybolur │ │
├───────────────────┼──────────────┼──────────────┼───────────────┤
│ git reset --soft │ Commit geri, │ ✅ Güvenli │ Commit'i │
│ │ staging'de │ │ yeniden yaz │
├───────────────────┼──────────────┼──────────────┼───────────────┤
│ git reset --mixed │ Commit geri, │ ✅ Güvenli │ Commit'i │
│ │ unstaged │ (dosyalar │ yeniden │
│ │ │ korunur) │ düzenle │
├───────────────────┼──────────────┼──────────────┼───────────────┤
│ git reset --hard │ Her şey geri │ ❌ Tehlikeli │ Son çare │
│ │ │ │ │
├───────────────────┼──────────────┼──────────────┼───────────────┤
│ git revert │ Ters commit │ ✅ Güvenli │ Push'lanmış │
│ │ oluşturur │ │ commit'ler │
├───────────────────┼──────────────┼──────────────┼───────────────┤
│ git commit --amend│ Son commit'i │ ✅ Güvenli │ Küçük │
│ │ değiştirir │ (yerel) │ düzeltmeler │
└───────────────────┴──────────────┴──────────────┴───────────────┘Pratik Senaryo: Gerçek Hayat
# Senaryo: Yanlışlıkla .env dosyasını commit'ledin!
# 1. Durumu gör
$ git log --oneline -3
c3d4e5f (HEAD -> main) feat: Yeni özellik
b2c3d4e chore: Config dosyaları ← .env burada!
a1b2c3d feat: Proje başlatıldı
# 2. Henüz push etmediysen → reset
$ git reset --soft HEAD~2
# Son 2 commit geri alındı, değişiklikler staging'de
$ git reset HEAD .env # .env'yi staging'den çıkar
$ echo ".env" >> .gitignore # .gitignore'a ekle
$ git add .gitignore
$ git add . # .env hariç her şey
$ git commit -m "feat: Yeni özellik ve config dosyaları (.env hariç)"
# 3. Zaten push ettiysen → revert + yeni commit
$ git rm --cached .env
$ echo ".env" >> .gitignore
$ git add .gitignore
$ git commit -m "security: .env dosyası izlemeden çıkarıldı"
$ git pushÖzet
`git restore` dosya düzeyinde geri alma yapar — working directory'yi veya staging'i etkiler, commit geçmişine dokunmaz
`git reset --soft` commit'i geri alır ama değişiklikler staging'de kalır — commit'leri birleştirmek için ideal
`git reset --mixed` (varsayılan) commit ve staging'i geri alır, değişiklikler working directory'de kalır
`git reset --hard` her şeyi geri alır — commit'lenmemiş değişiklikler kaybolur, son çare olarak kullan
`git revert` güvenli geri alma yapar — yeni commit oluşturur, geçmişi değiştirmez, push'lanmış commit'ler için kullan
`git reflog` kayıp commit'leri kurtarmak için son çaredir — HEAD'in 30 günlük hareketlerini kaydeder
*Tebrikler! Git'in temel komutlarını tamamladın. Bir sonraki bölümde dallanma (branching) dünyasına gireceğiz — Git'in en güçlü özelliği!*
AI Asistan
Sorularını yanıtlamaya hazır