← Kursa Dön
📄 Text · 30 min

İleri Komutlar

Giriş — Kayıp Eşyalar Bürosu

Bir havalimanı düşünün. Yolcular her gün eşya kaybeder — çanta, telefon, pasaport. Ama havalimanının bir "kayıp eşyalar bürosu" vardır. Burada kaybedilen her şey belirli bir süre saklanır. Eşyanızı ne zaman kaybettiğinizi ve kabaca nerede olduğunu biliyorsanız, geri alabilirsiniz.

Git'in reflog'u tam olarak bu kayıp eşyalar bürosudur. git reset --hard yaptınız ve commit'leriniz kayboldu mu? Branch'i yanlışlıkla sildiniz mi? Rebase karmaşası yüzünden kod kayboldu mu? Panik yapmayın — Git neredeyse hiçbir şeyi gerçekten silmez. Bu derste kayıp commit'leri nasıl kurtaracağınızı, repo'nuzun sağlığını nasıl kontrol edeceğinizi ve Git'in iç işleyişindeki güvenlik ağlarını öğreneceğiz.

git reflog — Git'in Gizli Günlüğü

Reflog Nedir?

Reflog (Reference Log), HEAD ve branch referanslarının her hareketini kaydeden yerel bir günlüktür. Her checkout, commit, reset, merge, rebase işlemi reflog'a yazılır.

# Reflog'u görüntüle
git reflog

# Çıktı:
abc1234 (HEAD -> main) HEAD@{0}: commit: feat: add payment module
def5678 HEAD@{1}: checkout: moving from feature to main
ghi9012 HEAD@{2}: commit: fix: resolve login bug
jkl3456 HEAD@{3}: rebase (finish): returning to refs/heads/feature
mno7890 HEAD@{4}: rebase (pick): feat: add user profile
pqr1234 HEAD@{5}: reset: moving to HEAD~3
stu5678 HEAD@{6}: commit: feat: add dashboard
vwx9012 HEAD@{7}: commit: feat: add sidebar
yza3456 HEAD@{8}: commit: feat: add navigation

Her satır şunu söyler:

abc1234          → Commit SHA
HEAD@{0}         → Kaç adım önce (0 = şu an)
commit: feat:... → Ne yapıldı

Reflog vs Log Farkı

# git log — commit geçmişini gösterir (branch'in bildiği commit'ler)
# git reflog — HEAD'in hareket geçmişini gösterir (silinen dahil!)

# Senaryo:
git commit -m "A"  # commit A
git commit -m "B"  # commit B  
git commit -m "C"  # commit C
git reset --hard HEAD~2  # A'ya geri dön

# git log sadece A'yı gösterir (B ve C "kayboldu")
# git reflog B ve C'yi de gösterir!
git log görünümü:              git reflog görünümü:
                               
  A ← HEAD                      HEAD@{0}: reset: HEAD~2
                                 HEAD@{1}: commit: C     ← BURADA!
                                 HEAD@{2}: commit: B     ← BURADA!
                                 HEAD@{3}: commit: A

Reflog Detaylı Kullanım

# Belirli branch'in reflog'u
git reflog show main
git reflog show feature/auth

# Zaman bazlı filtreleme
git reflog --since="2 hours ago"
git reflog --since="yesterday"
git reflog --since="2024-01-15"

# Detaylı format
git reflog --format='%C(yellow)%h %C(green)%gd %C(blue)%gs %C(reset)%s'

💡 İpucu: Reflog yereldir — remote'ta yoktur. Her geliştiricinin kendi reflog'u var. git push veya git clone ile aktarılmaz. Reflog varsayılan olarak 90 gün tutulur.

Kurtarma Senaryoları

Senaryo 1: git reset --hard Sonrası Kurtarma

En yaygın "felaket" senaryosu:

# Durum: 3 commit'i yanlışlıkla sildik
git reset --hard HEAD~3
# "Oh hayır! 2 günlük çalışmam gitti!"

# Kurtarma:
# 1. Reflog'da kayıp commit'i bul
git reflog
# abc1234 HEAD@{0}: reset: moving to HEAD~3
# def5678 HEAD@{1}: commit: feat: add payment validation  ← BU!
# ghi9012 HEAD@{2}: commit: feat: add payment form
# jkl3456 HEAD@{3}: commit: feat: add payment model

# 2. Kayıp commit'e geri dön
git reset --hard def5678
# HEAD is now at def5678 feat: add payment validation

# Tüm commit'ler geri geldi! 🎉

Senaryo 2: Silinen Branch'i Kurtarma

# Durum: Branch'i yanlışlıkla sildik
git branch -D feature/important-work
# Deleted branch feature/important-work (was abc1234).

# "O branch'te 1 haftalık çalışma vardı!"

# Kurtarma:
# 1. Silinme anındaki commit SHA'yı bul
git reflog | grep "feature/important-work"
# veya silme mesajındaki SHA'yı kullan: abc1234

# 2. O commit'ten yeni branch oluştur
git branch feature/important-work abc1234
git checkout feature/important-work

# Branch ve tüm commit'leri geri geldi! 🎉

Senaryo 3: Kötü Giden Rebase'i Kurtarma

# Durum: Interactive rebase sırasında bir şeyler karıştı
git rebase -i HEAD~5
# ... bazı commit'leri sildiniz, squash yanlış gitti ...
# Sonuç: kod bozuldu, commit'ler kayıp

# Kurtarma:
# 1. Rebase öncesi durumu bul
git reflog
# abc1234 HEAD@{0}: rebase (finish): returning to refs/heads/feature
# def5678 HEAD@{1}: rebase (squash): feat: combined commit
# ghi9012 HEAD@{2}: rebase (start): checkout main
# jkl3456 HEAD@{3}: commit: feat: my last good commit  ← REBASE ÖNCESİ

# 2. Rebase öncesine dön
git reset --hard jkl3456
# veya rebase sırasındayken:
git rebase --abort

Senaryo 4: Yanlış Merge'i Geri Alma

# Durum: Yanlış branch'i merge ettik
git merge wrong-branch
# Auto-merging...
# Merge made by the 'recursive' strategy.

# Kurtarma:
# 1. Merge öncesi commit'i bul
git reflog
# abc1234 HEAD@{0}: merge wrong-branch: Merge made by recursive
# def5678 HEAD@{1}: checkout: moving from feature to main  ← MERGE ÖNCESİ

# 2. Merge öncesine dön
git reset --hard def5678

# veya merge commit'i revert et (geçmişi koruyarak)
git revert -m 1 abc1234

Senaryo 5: Stash Drop Sonrası Kurtarma

# Durum: Stash'i yanlışlıkla drop ettik
git stash drop
# Dropped refs/stash@{0} (abc123def456789...)

# Kurtarma:
# 1. Dangling commit'leri bul
git fsck --no-reflogs | grep commit
# dangling commit abc123def456789

# 2. İçeriğini kontrol et
git show abc123def456789

# 3. Geri uygula
git stash apply abc123def456789
# veya branch oluştur
git branch recovered-stash abc123def456789

git fsck — Repo Sağlık Kontrolü

fsck Nedir?

fsck (File System Check), Git object veritabanının bütünlüğünü kontrol eder. Bozuk object'leri, yetim (dangling) commit'leri ve tutarsızlıkları tespit eder.

# Temel sağlık kontrolü
git fsck

# Çıktı (sağlıklı repo):
# Checking object directories: 100% (256/256), done.
# Checking objects: 100% (1234/1234), done.

# Çıktı (sorunlu repo):
# Checking object directories: 100% (256/256), done.
# dangling commit abc1234def5678901234567890abcdef12345678
# dangling blob def5678abc1234567890123456789abcdef012345
# dangling tree ghi9012345678901234567890abcdef0123456789

Dangling Objects Nedir?

Dangling (Yetim/Sarkan) Object:
Hiçbir branch, tag veya reflog tarafından referans edilmeyen
ama hâlâ .git/objects/ içinde var olan object'ler.

Nasıl oluşur?
- git reset --hard (commit'ler artık branch'te değil)
- git branch -D (branch silindi ama commit'ler kaldı)
- git rebase (eski commit'ler replaced ama silinmedi)
- git stash drop (stash commit'i referanssız kaldı)
- git commit --amend (eski commit replaced)
# Dangling object'leri bul
git fsck --no-reflogs
# dangling commit abc1234...
# dangling commit def5678...
# dangling blob ghi9012...

# Dangling commit'in içeriğini gör
git show abc1234
# commit abc1234...
# Author: Ahmet <ahmet@email.com>
# Date:   Mon Jan 15 10:30:00 2024
#
#     feat: add user authentication
#
# diff --git a/src/auth.js b/src/auth.js
# ...

# Eğer kurtarmak istiyorsanız:
git branch recovered abc1234

Detaylı fsck

# Tam kontrol (yavaş ama kapsamlı)
git fsck --full

# Ulaşılamayan (unreachable) object'leri göster
git fsck --unreachable

# Sadece dangling'leri göster
git fsck --dangling

# Bozuk object'leri kontrol et
git fsck --strict

git gc — Çöp Toplama

gc Nedir?

gc (Garbage Collection), gereksiz dosyaları temizler ve repo'yu optimize eder:

# Otomatik gc (Git gerektiğinde kendisi çalıştırır)
git gc --auto

# Manuel gc
git gc

# Agresif gc (daha iyi sıkıştırma, daha yavaş)
git gc --aggressive

# gc ne yapar:
# 1. Loose object'leri packfile'a sıkıştırır
# 2. Dangling object'leri siler (expire süresi geçmişse)
# 3. Reflog'u temizler (expire süresi geçmişse)
# 4. Boş dizinleri temizler

gc ve Kurtarma Süresi

# Dangling object'ler hemen silinmez!
# Varsayılan: 2 hafta sonra gc tarafından temizlenir

# gc expire süresini kontrol et
git config gc.pruneExpire
# default: 2.weeks.ago

# Reflog expire süresi
git config gc.reflogExpire
# default: 90.days

# DİKKAT: Bu komutu çalıştırırsanız dangling'ler HEMEN silinir
git gc --prune=now  # ⚠️ Kurtarma şansınız kaybolur!
Kurtarma Zaman Çizelgesi:

  Commit kaybı
       │
       ├── 0-90 gün: reflog'dan kurtarılabilir ✅
       │
       ├── 90 gün sonra: reflog temizlenir
       │   └── Ama dangling object hâlâ var ✅
       │
       ├── 14 gün sonra (gc çalışırsa): dangling silinir ❌
       │
       └── gc --prune=now: HEMEN silinir ❌

💡 İpucu: Kritik bir kurtarma yapmanız gerekiyorsa, önce gc çalıştırmayın! gc, kurtarabileceğiniz dangling object'leri silebilir.

Gelişmiş Kurtarma Teknikleri

Cherry-pick ile Kısmi Kurtarma

Tüm branch'i değil, sadece belirli commit'leri kurtarmak istiyorsanız:

# 1. Kayıp commit'leri bul
git reflog | grep "feat: important"
# abc1234 HEAD@{5}: commit: feat: important feature part 1
# def5678 HEAD@{4}: commit: feat: important feature part 2

# 2. Sadece ihtiyacınız olan commit'leri al
git cherry-pick abc1234
git cherry-pick def5678

Patch ile Kurtarma

Commit'i doğrudan uygulayamıyorsanız patch olarak çıkarabilirsiniz:

# 1. Kayıp commit'i patch'e çıkar
git show abc1234 > recovery.patch

# 2. Patch'i incele
cat recovery.patch

# 3. Patch'i uygula
git apply recovery.patch
git add .
git commit -m "recovered: important feature"

Lost Merge Commit Kurtarma

# Merge commit'in parent'larını bul
git cat-file -p abc1234
# tree def567890...
# parent 111222333...  ← ilk parent (merge yapılan branch)
# parent 444555666...  ← ikinci parent (merge edilen branch)
# author ...
# committer ...
#
# Merge branch 'feature' into main

# Bu parent SHA'lardan branch oluşturabilirsiniz
git branch recovered-main 111222333
git branch recovered-feature 444555666

git blame ile Soruşturma

git blame doğrudan bir kurtarma aracı olmasa da, "bu satırı kim, ne zaman, neden değiştirdi?" sorusuna cevap verir:

# Her satırın son değiştirilme bilgisi
git blame src/api/handler.js

# Çıktı:
# abc1234 (Ahmet  2024-01-15 10:30  1) const express = require('express');
# abc1234 (Ahmet  2024-01-15 10:30  2)
# def5678 (Mehmet 2024-01-20 14:15  3) // Handle payment processing
# ghi9012 (Ayşe  2024-02-01 09:00  4) async function processPayment(req) {
# ghi9012 (Ayşe  2024-02-01 09:00  5)   const { amount, currency } = req.body;

# Belirli satır aralığı
git blame -L 10,20 src/api/handler.js

# Belirli bir commit'ten önceki durumu göster
git blame abc1234^ -- src/api/handler.js

# Satır taşınmalarını/kopyalanmalarını takip et
git blame -C -C src/api/handler.js

# Whitespace değişikliklerini yoksay
git blame -w src/api/handler.js

💡 İpucu: git blame'i "suçlama" için değil, "anlama" için kullanın. Bir satırın neden böyle yazıldığını anlamak, o satırı değiştirmeden önce çok önemlidir. Commit mesajını okumak genellikle kodu okumaktan daha aydınlatıcıdır.

Repo Bakımı ve Sağlık Kontrolü

Düzenli Bakım Checklist'i

# 1. Repo boyutunu kontrol et
du -sh .git/
git count-objects -vH

# 2. Sağlık kontrolü
git fsck --full

# 3. Gereksiz object'leri temizle
git gc

# 4. Remote'tan silinmiş branch referanslarını temizle
git remote prune origin
# veya fetch ile birlikte:
git fetch --prune

# 5. Merge edilmiş local branch'leri temizle
git branch --merged main | grep -v "main" | xargs git branch -d

git maintenance (Git 2.29+)

Modern Git, otomatik bakım komutu sunar:

# Otomatik bakımı başlat
git maintenance start

# Bu komut şunları otomatik yapar:
# - Hourly: prefetch (remote'dan arka planda fetch)
# - Daily: loose-objects (loose object'leri packle)
# - Daily: incremental-repack (packfile'ları optimize et)
# - Weekly: pack-refs (referansları pack et)

# Bakım durumunu kontrol et
git maintenance run --task=gc
git maintenance run --task=commit-graph

# Otomatik bakımı durdur
git maintenance stop

Gerçek Dünya Senaryosu: Cuma Günü Felaketi

# Senaryo: Cuma 17:00, sprint kapanışı, acele ediyorsunuz

# 1. Yanlış branch'tesiniz ama fark etmediniz
git checkout main  # Aslında feature'da olmalıydınız
git commit -m "feat: finish sprint task"
git push origin main  # Oops! Main'e direkt push!

# 2. Panik — geri al!
git reset --hard HEAD~1
git push --force origin main  # Force push ile geri aldınız

# 3. AMA! O commit'teki kod lazım!
# Kurtarma:
git reflog
# abc1234 HEAD@{0}: reset: moving to HEAD~1
# def5678 HEAD@{1}: commit: feat: finish sprint task  ← BU!

# 4. Doğru branch'te uygula
git checkout feature/sprint-task
git cherry-pick def5678

# 5. PR aç, review al, merge et (doğru şekilde)
git push origin feature/sprint-task
gh pr create --title "feat: finish sprint task"

# Felaket önlendi! 🎉
# Ders: Branch protection açık olsaydı,
# main'e direkt push edemezdik.

git bisect — Binary Search ile Bug Arama

git bisect, binary search algoritmasıyla bug'ın hangi commit'te girdiğini bulur. 1000 commit arasında bile 10 adımda suçlu commit'i tespit eder:

# Bisect başlat
$ git bisect start

# Bu commit'te bug var (bad)
$ git bisect bad HEAD

# Bu eski commit'te bug yoktu (good)
$ git bisect good v1.0.0

# Git ortadaki bir commit'e checkout yapar
# Bisecting: 256 revisions left to test
# [abc1234] feat: Add payment module

# Test et — bug var mı?
$ npm test
# Bug var → bad
$ git bisect bad

# Git yeni bir commit'e checkout yapar
# Bisecting: 128 revisions left to test
# [def5678] refactor: Update auth module

# Test et
$ npm test
# Bug yok → good
$ git bisect good

# ... birkaç adım daha ...
# abc1234 is the first bad commit
# commit abc1234
# Author: Mehmet <mehmet@email.com>
# Date:   Mon Feb 15 2026
#
#     feat: Add caching layer
#
# Bug bu commit'te girmiş! 🎯

# Bisect'i bitir
$ git bisect reset

Otomatik Bisect

Eğer bug'ı tespit eden bir test/script varsa, bisect'i otomatikleştirebilirsiniz:

# Otomatik bisect — script 0 dönerse good, 1+ dönerse bad
$ git bisect start HEAD v1.0.0
$ git bisect run npm test

# veya özel script
$ git bisect run ./check-bug.sh
# Git otomatik olarak binary search yapar ve suçlu commit'i bulur!

Komut Referans Tablosu

Durum                         │ Çözüm
──────────────────────────────┼──────────────────────────────
reset --hard geri al          │ git reflog → git reset --hard SHA
Silinen branch kurtarma       │ git reflog → git branch name SHA
Kötü rebase geri al           │ git reflog → git reset --hard SHA
                              │ veya git rebase --abort
Stash drop kurtarma           │ git fsck --no-reflogs → git stash apply SHA
Amend öncesi commit kurtarma  │ git reflog → git cherry-pick SHA
Merge geri alma               │ git reset --hard MERGE_HEAD~1
                              │ veya git revert -m 1 MERGE_SHA
Bozuk repo tespiti            │ git fsck --full
Repo optimize etme            │ git gc --aggressive
Kayıp dosya arama             │ git log --all --full-history -- path
Remote stale branch temizleme │ git fetch --prune

Yaygın Hatalar

1. Reflog'un Yerel Olduğunu Unutmak

# ❌ "Reflog'dan kurtarabilirim" deyip repo'yu silmek
rm -rf my-repo
git clone origin my-repo
git reflog  # BOŞ! Reflog yereldi, clone ile gelmez!

# ✅ Kritik kurtarmadan önce repo'yu yedekleyin
cp -r my-repo my-repo-backup

2. gc --prune=now Acele Çalıştırmak

# ❌ Kurtarma gerektiren durumda gc çalıştırmak
git reset --hard HEAD~5  # 5 commit kayboldu
git gc --prune=now        # Dangling object'ler silindi!
# Artık kurtarılamaz! 💀

# ✅ Önce kurtarma, sonra temizlik
git reflog  # Kayıp commit'i bul
git reset --hard abc1234  # Kurtarma yap
# ... her şey yolunda olunca ...
git gc  # Şimdi temizlik güvenli

3. Force Push Sonrası Kurtarmaya Güvenmek

# ❌ "Nasılsa reflog var" diyerek force push yapmak
git push --force origin main
# Ekip üyelerinin local'indeki reflog SİZİN reflog'unuz değil!

# ✅ Force push öncesi düşünün
# - Ekibi bilgilendirin
# - --force-with-lease kullanın
# - Branch protection açık olsun

Özet

Bu derste Git'in kurtarma ve bakım araçlarını öğrendik:

  • 📋 git reflog — HEAD'in hareket geçmişi, kayıp commit'leri bulma

  • 🔄 reset kurtarmagit reflog + git reset --hard SHA ile geri dönüş

  • 🌿 branch kurtarma — silinen branch'i reflog'dan geri oluşturma

  • 🔍 git fsck — repo sağlık kontrolü, dangling object'leri tespit

  • 🧹 git gc — çöp toplama, repo optimizasyonu

  • Kurtarma penceresi — reflog 90 gün, dangling 2 hafta

  • 🔧 git maintenance — otomatik bakım, arka plan optimizasyonu

  • 👀 git blame — satır bazlı geçmiş soruşturması


💡 Son İpucu: Reflog, Git'in en az bilinen ama en hayat kurtarıcı özelliğidir. Kural: panik yapmadan önce her zaman git reflog çalıştırın. Git neredeyse hiçbir şeyi gerçekten silmez — 90 gün boyunca her şeyi hatırlar. Bu bilgi bir gece yarısı production hotfix'inde hayatınızı kurtarabilir.

Bir sonraki derste büyük repo'ların performans optimizasyonunu ele alacağız: sparse checkout, partial clone, commit graph ve scalar.