← Kursa Dön
📄 Text · 30 min

Geçmişi İnceleme: log ve diff

Giriş: Neden Geçmişe Bakmayı Öğreniyoruz?

Bir yazılım projesinde en kritik anlardan biri "Bu bug ne zaman girdi?" veya "Bu dosyayı kim, neden değiştirdi?" dediğin andır. Git, her değişikliğin kaydını tutuyor ama bu kayıtlara nasıl erişeceğini bilmen gerekiyor.

Git'in geçmiş inceleme araçları bir dedektifin araçları gibidir:

  • git log — olay yerinin genel fotoğrafı. Ne zaman, kim, ne yaptı?

  • git diff — iki durum arasındaki farkları satır satır gösterir

  • git show — belirli bir olayın detaylarını inceler

Bu üç komut, günlük çalışmada en çok kullanacağın araçlar arasında. Gelin derinlemesine öğrenelim.


🎬 Analoji: Güvenlik Kamerası Kayıtları

Bir binanın güvenlik kamerası sistemini düşün:

  • `git log` = Kayıtların listesi. "14:32 — Giriş kapısı, Ali girdi. 14:45 — 3. kat, Ayşe çıktı." Kronolojik olaylar.

  • `git diff` = İki kare arasındaki fark. "14:32'deki kare ile 14:45'deki kareyi karşılaştır — masanın üzerinde yeni bir dosya var."

  • `git show` = Belirli bir anın detaylı görüntüsü. "14:32'deki karenin tam görüntüsünü göster — kim var, ne yapıyor, ortam nasıl?"


git log — Geçmişin Haritası

Temel Kullanım

$ git log
commit d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3 (HEAD -> main)
Author: Tolgahan Kaya <tolgahan@example.com>
Date:   Mon Mar 1 12:00:00 2026 +0300

    feat: İletişim formu eklendi

commit a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
Author: Tolgahan Kaya <tolgahan@example.com>
Date:   Mon Mar 1 11:30:00 2026 +0300

    feat: Hakkımda sayfası oluşturuldu

commit h7i8j9k0l1m2n3o4p5q6r7s8t9u0v1w2x3y4z5a6
Author: Tolgahan Kaya <tolgahan@example.com>
Date:   Mon Mar 1 10:00:00 2026 +0300

    feat: Proje başlatıldı

Bu varsayılan çıktı çok yer kaplar. En son commit'ten geriye doğru sıralıdır. Çok commit varsa uzar gider — q tuşuna basarak çıkabilirsin (less pager'ı kullanır).

--oneline: Kompakt Görünüm

$ git log --oneline
d4e5f6g (HEAD -> main) feat: İletişim formu eklendi
a1b2c3d feat: Hakkımda sayfası oluşturuldu
h7i8j9k feat: Proje başlatıldı

Her commit bir satır. Hızlı tarama için mükemmel.

--graph: ASCII Grafik

Branch'ler ve merge'ler olduğunda hayat kurtarır:

$ git log --oneline --graph --all
* f7g8h9i (HEAD -> main) Merge branch 'feature/contact'
|\
| * e6f7g8h (feature/contact) feat: İletişim formu validasyonu
| * d5e6f7g feat: İletişim formu HTML yapısı
|/
* c4d5e6f feat: Hakkımda sayfası
* b3c4d5e feat: Header ve navigasyon
* a2b3c4d feat: Proje başlatıldı

Bu ASCII grafiği branch'lerin nasıl dallandığını ve birleştiğini görsel olarak gösterir.

--stat: Hangi Dosyalar Değişmiş?

$ git log --stat --oneline
d4e5f6g (HEAD -> main) feat: İletişim formu eklendi
 index.html    | 12 ++++++++++++
 css/style.css |  8 ++++++++
 js/contact.js |  5 +++++
 3 files changed, 25 insertions(+)

a1b2c3d feat: Hakkımda sayfası oluşturuldu
 about.html    | 18 ++++++++++++++++++
 css/style.css |  4 ++++
 2 files changed, 22 insertions(+)

Her commit'te hangi dosyaların değiştiğini ve kaç satır eklendiğini/silindiğini gösterir. + ve - ile değişiklik miktarı grafiksel olarak da gösterilir.

-p veya --patch: Tam Diff Görünümü

$ git log -p -1
# Son commit'in tam diff'ini gösterir

commit d4e5f6g (HEAD -> main)
Author: Tolgahan Kaya <tolgahan@example.com>
Date:   Mon Mar 1 12:00:00 2026 +0300

    feat: İletişim formu eklendi

diff --git a/index.html b/index.html
--- a/index.html
+++ b/index.html
@@ -15,5 +15,17 @@
     </section>
+    <section id="contact">
+        <h2>İletişim</h2>
+        <form id="contactForm">
+            <input type="text" placeholder="Adınız">
+            <input type="email" placeholder="E-posta">
+            <textarea placeholder="Mesajınız"></textarea>
+            <button type="submit">Gönder</button>
+        </form>
+    </section>

Filtreleme: İğneyi Samanlıkta Bulmak

git log'un asıl gücü filtreleme seçeneklerinde:

# Son N commit
$ git log -5                        # Son 5 commit

# Tarih aralığı
$ git log --since="2026-02-01"      # 1 Şubat'tan bu yana
$ git log --after="2 weeks ago"     # Son 2 hafta
$ git log --until="2026-02-28"      # 28 Şubat'a kadar
$ git log --since="2026-02-01" --until="2026-02-28"  # Şubat ayı

# Yazar filtresi
$ git log --author="Tolgahan"       # Tolgahan'ın commit'leri
$ git log --author="ali\|ayse"      # Ali veya Ayşe (regex)

# Mesaj filtresi
$ git log --grep="fix"              # Mesajında "fix" geçenler
$ git log --grep="login" -i         # Case-insensitive

# Dosya filtresi
$ git log -- index.html             # Sadece index.html'i etkileyen
$ git log -- "*.css"                # Tüm CSS dosyalarını etkileyen
$ git log -- src/                   # src/ klasörünü etkileyen

# İçerik filtresi (pickaxe)
$ git log -S "getElementById"       # Bu stringi ekleyen/silen commit'ler
$ git log -G "user.*login"          # Regex ile içerik arama

# Birleştirme
$ git log --author="Tolgahan" --since="1 week ago" --oneline
# Tolgahan'ın son 1 haftadaki commit'leri

Format: Özel Çıktı

# Özel format
$ git log --pretty=format:"%h - %an, %ar : %s"
d4e5f6g - Tolgahan Kaya, 2 hours ago : feat: İletişim formu eklendi
a1b2c3d - Tolgahan Kaya, 3 hours ago : feat: Hakkımda sayfası
h7i8j9k - Tolgahan Kaya, 5 hours ago : feat: Proje başlatıldı

Format placeholder'ları:

%H  = Tam hash
%h  = Kısa hash
%an = Author adı
%ae = Author e-postası
%ar = Author tarihi (relative — "2 hours ago")
%ad = Author tarihi (absolute)
%s  = Commit mesajı (başlık)
%b  = Commit mesajı (gövde)
%d  = Referanslar (HEAD -> main)

Renkli çıktı:

$ git log --pretty=format:"%C(red)%h%C(reset) - %C(green)%an%C(reset), %C(blue)%ar%C(reset) : %s"

💡 İpucu: En çok kullanacağın kombinasyonu alias olarak kaydet: ``bash git config --global alias.lg "log --oneline --graph --all --decorate" git config --global alias.hist "log --pretty=format:'%h %ad | %s%d [%an]' --date=short" ``


git diff — Farkları Görmek

git diff, Git'in en güçlü karşılaştırma aracıdır. Farklı durumları karşılaştırır.

Diff Çıktısını Okumak

Önce diff çıktısının formatını anlayalım:

$ git diff
diff --git a/index.html b/index.html
index 7c8d9e0..a1b2c3d 100644
--- a/index.html
+++ b/index.html
@@ -10,7 +10,9 @@
 <body>
     <header>
         <h1>Merhaba Dünya</h1>
-        <p>Eski paragraf</p>
+        <p>Yeni paragraf</p>
+        <p>Ek bilgi</p>
     </header>
+    <footer>© 2026</footer>
 </body>

Her satırı açıklayalım:

diff --git a/index.html b/index.html
│         │               │
│         ▼               ▼
│     eski versiyon   yeni versiyon
▼
diff komutu

--- a/index.html        ← Eski dosya (a = before)
+++ b/index.html        ← Yeni dosya (b = after)

@@ -10,7 +10,9 @@      ← Hunk header
│    │  │  │  │
│    │  │  │  └── yeni dosyada 9 satır gösteriliyor
│    │  │  └──── yeni dosyada 10. satırdan başlıyor
│    │  └─────── eski dosyada 7 satır gösteriliyor
│    └────────── eski dosyada 10. satırdan başlıyor
└──────────────── hunk sınırları

 (boşluk) = değişmemiş satır (context)
-           = silinen satır (kırmızı)
+           = eklenen satır (yeşil)

diff Kullanım Senaryoları

┌────────────────┐        ┌────────────────┐        ┌────────────────┐
│    Working     │        │    Staging     │        │   Repository   │
│   Directory    │        │     Area      │        │    (HEAD)      │
└───────┬────────┘        └───────┬────────┘        └───────┬────────┘
        │                         │                         │
        │◄── git diff ──────────►│                         │
        │                         │                         │
        │                         │◄── git diff --staged ─►│
        │                         │                         │
        │◄── git diff HEAD ─────────────────────────────► │
# 1. Working Directory vs Staging Area
$ git diff
# "Stage'e almadığım değişiklikler neler?"

# 2. Staging Area vs Son Commit
$ git diff --staged
# veya (aynı şey):
$ git diff --cached
# "Commit'leyeceğim değişiklikler neler?"

# 3. Working Directory vs Son Commit
$ git diff HEAD
# "Tüm değişikliklerim neler? (staged + unstaged)"

İki Commit Arasındaki Fark

# İki commit arasındaki fark
$ git diff a1b2c3d d4e5f6g
# a1b2c3d'den d4e5f6g'ye ne değişti?

# Son commit ile bir önceki arasındaki fark
$ git diff HEAD~1 HEAD
# veya
$ git diff HEAD~1

# Son 3 commit'te ne değişti
$ git diff HEAD~3 HEAD

Belirli Dosya İçin Diff

# Sadece bir dosyanın farkı
$ git diff -- index.html

# Staging'deki belirli dosya
$ git diff --staged -- style.css

# İki commit arasında belirli dosya
$ git diff a1b2c3d d4e5f6g -- index.html

Word Diff: Satır Yerine Kelime Bazlı

Normal diff satır bazlıdır. Ama bazen bir satırda sadece bir kelime değişmiştir:

# Normal diff
$ git diff
-        <h1>Merhaba Dünya</h1>
+        <h1>Merhaba Git Dünyası</h1>
# Tüm satır yeniden yazılmış gibi görünüyor

# Word diff
$ git diff --word-diff
        <h1>Merhaba [-Dünya-]{+Git Dünyası+}</h1>
# Sadece değişen kelimeler vurgulanmış

Sadece Dosya İsimlerini Göster

# Hangi dosyalar değişmiş (fark detayı olmadan)
$ git diff --name-only HEAD~3 HEAD
index.html
css/style.css
js/app.js

# Durumuyla birlikte
$ git diff --name-status HEAD~3 HEAD
M       index.html        # Modified
A       css/style.css     # Added
D       old-file.txt      # Deleted
R100    a.txt   b.txt     # Renamed (100% benzerlik)

İstatistik Görünümü

$ git diff --stat HEAD~3 HEAD
 index.html    | 12 ++++++++----
 css/style.css |  8 ++++++++
 js/app.js     |  3 ++-
 3 files changed, 19 insertions(+), 5 deletions(-)

⚠️ Dikkat: git diff sadece izlenen (tracked) dosyaları gösterir. Yeni oluşturulan ama henüz git add yapılmamış dosyalar diff'te gözükmez. Onlar git status'ta "Untracked" olarak görünür.


git show — Belirli Bir Anı İncele

git show belirli bir commit'in, tag'in veya nesnenin detaylarını gösterir.

Commit Gösterme

# Son commit'in detayları
$ git show
commit d4e5f6g (HEAD -> main)
Author: Tolgahan Kaya <tolgahan@example.com>
Date:   Mon Mar 1 12:00:00 2026 +0300

    feat: İletişim formu eklendi

diff --git a/index.html b/index.html
...
# (diff çıktısı)

# Belirli bir commit
$ git show a1b2c3d
# a1b2c3d commit'inin detayları + diff

# Sadece mesajı göster (diff olmadan)
$ git show --stat a1b2c3d
commit a1b2c3d
Author: Tolgahan Kaya <tolgahan@example.com>
Date:   Mon Mar 1 11:30:00 2026 +0300

    feat: Hakkımda sayfası oluşturuldu

 about.html    | 18 ++++++++++++++++++
 css/style.css |  4 ++++
 2 files changed, 22 insertions(+)

Belirli Bir Commit'teki Dosyayı Gösterme

# 2 commit önceki index.html nasılmış?
$ git show HEAD~2:index.html
<!DOCTYPE html>
<html>
<head><title>Web Projem</title></head>
<body>
    <h1>Merhaba Dünya</h1>
</body>
</html>

# Belirli bir commit'teki dosya
$ git show a1b2c3d:style.css
body { margin: 0; }

Bu, dosyanın eski bir versiyonunu okumak için çok pratik. Dosyayı geri yüklemeden sadece bakabilirsin.

Commit Referansları

Git'te commit'lere erişmenin farklı yolları:

# Hash ile (en yaygın)
$ git show a1b2c3d

# HEAD referansı ile
$ git show HEAD          # Son commit
$ git show HEAD~1        # Bir önceki commit
$ git show HEAD~2        # İki önceki commit
$ git show HEAD~5        # Beş önceki commit

# Branch adı ile
$ git show main          # main branch'inin son commit'i
$ git show feature       # feature branch'inin son commit'i

# Şapka (^) ile parent seçme (merge commit'lerde)
$ git show HEAD^         # İlk parent (= HEAD~1)
$ git show HEAD^2        # İkinci parent (merge'deki diğer branch)
HEAD~ vs HEAD^ :

Düz zincirde ikisi aynı:
[A] ← [B] ← [C]    HEAD = C, HEAD~1 = HEAD^ = B

Merge commit'te farklı:
      [D]
     /   \
[A]←[B]   [E] ← HEAD (merge commit)
     \   /
      [C]

HEAD^  = HEAD^1 = D (birinci parent — merge'ün yapıldığı branch)
HEAD^2 = C          (ikinci parent — merge edilen branch)
HEAD~1 = D          (bir önceki — birinci parent takip edilir)
HEAD~2 = B          (iki önceki — birinci parent zinciri)

💡 İpucu: HEAD~N "N adım geriye git (her zaman birinci parent'ı takip ederek)" demektir. HEAD^N ise "N'inci parent'ı seç" demektir. Düz zincirde fark yok, merge commit'lerde önemli.


git blame — Kim Yazdı Bu Satırı?

git blame her satırın son kez kim tarafından, ne zaman değiştirildiğini gösterir:

$ git blame index.html
a1b2c3d4 (Tolgahan 2026-03-01 10:00:00)  1) <!DOCTYPE html>
a1b2c3d4 (Tolgahan 2026-03-01 10:00:00)  2) <html lang="tr">
a1b2c3d4 (Tolgahan 2026-03-01 10:00:00)  3) <head>
b2c3d4e5 (Ali      2026-03-02 14:30:00)  4)     <meta charset="UTF-8">
b2c3d4e5 (Ali      2026-03-02 14:30:00)  5)     <title>Web Projem</title>
a1b2c3d4 (Tolgahan 2026-03-01 10:00:00)  6) </head>
d4e5f6g7 (Ayşe    2026-03-03 09:15:00)  7) <body>
d4e5f6g7 (Ayşe    2026-03-03 09:15:00)  8)     <h1>Merhaba Git!</h1>
# Belirli satır aralığını göster
$ git blame -L 5,10 index.html
# 5. satırdan 10. satıra kadar

# Satırı kimin değiştirdiğinin ötesinde, 
# taşıma/kopyalamayı da tespit et
$ git blame -C index.html

git log --all --oneline --graph — En Kullanışlı Kombinasyon

Bu kombinasyon, projenin tüm branch'lerini grafik olarak görüntüler — hemen alias olarak kaydedin:

# Alias ekle (bir kez yap, her zaman kullan)
$ git config --global alias.adog "log --all --decorate --oneline --graph"

# Kullanım
$ git adog
* f7g8h9i (HEAD -> main) feat: Son commit
| * e6f7g8h (feature/login) feat: Login formu
| * d5e6f7g feat: Auth modülü
|/
* c4d5e6f feat: Proje başlangıcı

💡 İpucu: git adog (All Decorate Oneline Graph) kolay hatırlanan bir kısaltma. Birçok geliştirici bunu günlük kullanır.


Pratik Senaryo: Bug Avı

Gerçek bir senaryoda bu araçları nasıl kullanacağını görelim:

# Senaryo: Login sayfası bozulmuş. Ne zaman, kim bozdu?

# 1. Login dosyasını etkileyen commit'leri bul
$ git log --oneline -- src/login.js
f7g8h9i fix: Login button styling
e6f7g8h feat: Remember me checkbox
d5e6f7g refactor: Auth module restructured
c4d5e6f feat: Login page created

# 2. Şüpheli commit'in detaylarına bak
$ git show d5e6f7g
# Refactoring'de bir şey bozulmuş olabilir

# 3. O commit'te tam olarak ne değişmiş?
$ git diff c4d5e6f d5e6f7g -- src/login.js
# İki commit arasındaki farkı gör

# 4. Belirli bir satırı kim yazmış?
$ git blame src/login.js -L 42,50
# 42-50. satırlar arasını incele

# 5. O commit'teki login.js'in eski haline bak
$ git show c4d5e6f:src/login.js
# Refactoring öncesindeki halini gör

# 6. Son 1 haftadaki tüm değişiklikleri listele
$ git log --since="1 week ago" --stat --oneline

git shortlog — Katkı Özeti

git shortlog, commit'leri yazarlara göre gruplar — proje istatistikleri için çok kullanışlıdır:

# Yazar bazlı commit sayıları
$ git shortlog -sn
    142  Tolgahan Kaya
     87  Ali Yılmaz
     53  Ayşe Demir
     21  Mehmet Can

# Son 30 günün katkıcıları
$ git shortlog -sn --since="30 days ago"
     23  Tolgahan Kaya
     15  Ali Yılmaz
      8  Ayşe Demir

# E-posta ile birlikte
$ git shortlog -sne
    142  Tolgahan Kaya <tolgahan@email.com>

Yararlı Kombinasyonlar

# "Bu hafta ne yaptım?" raporu
$ git log --author="$(git config user.name)" --since="monday" --oneline

# En çok değişen dosyalar (son 50 commit)
$ git log --pretty=format: --name-only -50 | sort | uniq -c | sort -rn | head -10

# Bugün yapılan commit'ler
$ git log --since="today" --oneline

# Merge commit'leri atla
$ git log --oneline --no-merges

# Sadece merge commit'leri göster
$ git log --oneline --merges

Özet

  • `git log` commit geçmişini gösterir — --oneline, --graph, --stat, --author, --since gibi bayraklarla filtrelenir

  • `git diff` iki durum arasındaki farkları satır satır gösterir — staging, working directory veya commit'ler arası

  • `git show` belirli bir commit'in detaylarını ve diff'ini gösterir — eski dosya versiyonlarına bakmak için de kullanılır

  • `git blame` her satırın en son kim tarafından değiştirildiğini gösterir — bug kaynağı bulmak için güçlü

  • HEAD~N ile N commit geriye gidebilir, commit:dosya sözdizimi ile eski dosya versiyonlarını okuyabilirsin

  • Diff çıktısında - silinen, + eklenen, boşlukla başlayan satırlar değişmeyen satırlardır



💡 Son İpucu: git log, git diff ve git show günlük en çok kullanacağın üç komuttur. Alias'larınızı kurun (git lg, git adog, git hist), sık kullandığınız filtreleri ezbere bilin. Bu komutlara ne kadar hakimsen, kodda o kadar hızlı yol alırsın.

*Bir sonraki derste hata yaptığında nasıl geri alacağını öğreneceğiz: git restore, git reset ve git revert — Git'in geri tuşları!*