← Kursa Dön
📄 Text · 30 min

Performans

Giriş — Süpermarket vs Toptan Depo

Bir süpermarket düşünün. Raflar düzenli, ürünler etiketli, ihtiyacınız olanı hızla bulup alabilirsiniz. Bir de toptan depo düşünün: binlerce palet, devasa alan, forklift gerekiyor. Bir paket bisküvi almak için tüm depoyu gezmek istemezsiniz.

Büyük Git repository'leri de toptan depoya benzer. Yüzlerce klasör, binlerce dosya, on binlerce commit. Sadece frontend klasöründe çalışan bir geliştirici, tüm repo'yu klonlamak ve tüm geçmişi çekmek zorunda mı? Hayır! Git, bu sorunu çözmek için güçlü araçlar sunuyor.

Bu derste, büyük repo'larda performansı nasıl artıracağınızı öğreneceğiz.

Büyük Repo Sorunları

Ne Zaman Repo "Büyük" Sayılır?

Boyut Kategorileri:
─────────────────────────────────────
Küçük     : < 100 MB, < 10K commit, < 1K dosya
Orta      : 100MB-1GB, 10K-100K commit, 1K-10K dosya
Büyük     : 1GB-10GB, 100K-1M commit, 10K-100K dosya
Devasa    : > 10GB, > 1M commit, > 100K dosya

Gerçek dünya örnekleri:
• Linux kernel: ~4GB, 1M+ commit, 75K+ dosya
• Chromium: ~15GB, 1M+ commit, 350K+ dosya
• Windows (VFS): ~300GB (Microsoft'un VFS for Git'i)
• Android: ~100GB (repo tool ile yönetilir)

Yavaşlık Belirtileri

# Bu komutlar yavaş mı çalışıyor?
git status          # > 5 saniye → Sorun var
git log             # > 3 saniye → Sorun var
git diff            # > 5 saniye → Sorun var
git clone           # > 10 dakika → Çok büyük repo
git checkout branch # > 30 saniye → Çok fazla dosya
git fetch           # > 5 dakika → Çok fazla geçmiş

Yavaşlığın Nedenleri

1. Büyük geçmiş (çok commit)
   → clone yavaş, fetch yavaş
   
2. Büyük dosyalar (binary, media)
   → clone yavaş, her checkout yavaş
   
3. Çok dosya (100K+)
   → status yavaş, checkout yavaş
   
4. Büyük tree'ler (derin klasör yapısı)
   → diff yavaş, merge yavaş

Partial Clone — Geçmişi İndirmeden Klonlama

Konsept

Normal git clone tüm geçmişi (her commit'in her dosyasını) indirir. Partial clone, sadece ihtiyacınız olan object'leri indirir, gerisini "lazım olunca" çeker.

Normal Clone:
  Tüm commit'ler ✓
  Tüm tree'ler ✓
  Tüm blob'lar ✓
  Toplam: 5GB indirme

Blobless Clone (--filter=blob:none):
  Tüm commit'ler ✓
  Tüm tree'ler ✓
  Blob'lar: sadece HEAD ✓ (geri kalan lazım olunca)
  Toplam: 500MB indirme

Treeless Clone (--filter=tree:0):
  Tüm commit'ler ✓
  Tree'ler: sadece HEAD ✓
  Blob'lar: sadece HEAD ✓
  Toplam: 100MB indirme

Blobless Clone (Önerilen)

En yaygın kullanım: commit geçmişini indir ama dosya içeriklerini sadece HEAD için al.

# Blobless clone — geçmiş dosya içerikleri indirilmez
git clone --filter=blob:none https://github.com/torvalds/linux.git

# Normal clone: ~4GB, ~20 dakika
# Blobless clone: ~500MB, ~3 dakika

# checkout yaptığınızda ihtiyaç olan blob'lar otomatik indirilir
cd linux
git checkout v6.7  # sadece bu tag'deki dosyalar indirilir
# Eski dosya içeriklerine eriştiğinizde:
git show HEAD~100:Makefile
# → Bu blob otomatik olarak server'dan çekilir (on-demand fetch)

git log -p -- kernel/sched/core.c
# → Her commit'in diff'i gösterilirken blob'lar çekilir

Treeless Clone

Daha agresif: tree object'leri de indirmez. Sadece commit graph ve HEAD'deki dosyalar.

# Treeless clone — en hızlı ama en kısıtlı
git clone --filter=tree:0 https://github.com/torvalds/linux.git

# Normal clone: ~4GB
# Treeless clone: ~100MB

# ⚠️ git log, git blame gibi geçmişe bakan komutlar
# her seferinde server'a istek atar — internet gerekli

Boyut Filtresi

Belirli boyutun üzerindeki blob'ları indirmemek:

# 1MB'dan büyük dosyaları indirme
git clone --filter=blob:limit=1m https://github.com/org/repo.git

# Checkout'ta sadece küçük dosyalar hazır olur
# Büyük dosyalara erişince otomatik indirilir

Karşılaştırma

Clone Türü          │ Boyut   │ Hız     │ Offline │ Uygunluk
────────────────────┼─────────┼─────────┼─────────┼──────────
Normal              │ 100%    │ Yavaş   │ Tam     │ Her durum
--filter=blob:none  │ ~10-20% │ Hızlı   │ Kısıtlı│ Geliştirme ✅
--filter=tree:0     │ ~2-5%   │ En hızlı│ Çok az  │ CI/CD ✅
--depth=1           │ ~5-10%  │ Hızlı   │ Kısıtlı│ CI/CD
--filter=blob:limit │ Değişken│ Hızlı   │ Kısıtlı│ LFS olmadan

💡 İpucu: Günlük geliştirme için --filter=blob:none en iyi denge. Commit geçmişi (log, blame) yerel çalışır, ama eski dosya içerikleri gerektiğinde network isteği yapar. Çoğu durumda bunu fark etmezsiniz bile.

Shallow Clone — Sığ Klonlama

Konsept

Shallow clone, sadece son N commit'i veya belirli bir tarihe kadar olan commit'leri indirir:

# Son 1 commit (en sığ)
git clone --depth=1 https://github.com/org/repo.git

# Son 10 commit
git clone --depth=10 https://github.com/org/repo.git

# Belirli bir tarihten itibaren
git clone --shallow-since="2024-01-01" https://github.com/org/repo.git

# Belirli bir branch'i shallow clone
git clone --depth=1 --branch=main https://github.com/org/repo.git

Shallow Clone Kısıtlamaları

# ❌ Shallow clone'da çalışmayanlar:
git log  # Sadece indirilen commit'ler görünür
git blame  # Geçmiş kısıtlı
git merge  # Ortak ata bulunamayabilir

# Shallow'u derinleştirme
git fetch --deepen=50  # 50 commit daha indir
git fetch --unshallow   # Tam geçmişi indir

CI/CD İçin Shallow Clone

CI pipeline'larında tam geçmiş nadiren gerekir:

# GitHub Actions — hızlı clone
- uses: actions/checkout@v4
  with:
    fetch-depth: 1  # Shallow clone (varsayılan)

# Tam geçmiş gerekiyorsa (semantic-release, changelog)
- uses: actions/checkout@v4
  with:
    fetch-depth: 0  # Tüm geçmiş

# Blobless clone (Actions v4 destekler)
- uses: actions/checkout@v4
  with:
    filter: 'blob:none'

Sparse Checkout — Kısmi Dosya İndirme

Konsept

Monorepo'da 10 klasör var ama siz sadece 1 klasörde çalışıyorsunuz. Neden diğer 9 klasörü de checkout ediyorsunuz? Sparse checkout, sadece belirttiğiniz dosya/klasörleri working directory'ye çıkarır.

Monorepo (tam checkout):          Sparse checkout:
acme-corp/                        acme-corp/
├── apps/                         ├── apps/
│   ├── frontend/  ← siz          │   ├── frontend/ ✅ (checkout edildi)
│   ├── backend/                  │   ├── backend/  ❌ (yok)
│   ├── mobile/                   │   └── mobile/   ❌ (yok)
│   └── admin/                    ├── packages/
├── packages/                     │   └── ui/       ✅ (bağımlılık)
│   ├── ui/                       └── package.json  ✅
│   ├── utils/
│   └── config/
├── infrastructure/
└── package.json

Sparse Checkout Kullanımı

# 1. Clone (blobless ile birleştirmek ideal)
git clone --filter=blob:none --sparse https://github.com/acme/monorepo.git
cd monorepo

# 2. Sparse checkout ayarla
git sparse-checkout init --cone

# 3. İstediğiniz klasörleri ekleyin
git sparse-checkout set apps/frontend packages/ui

# Sadece bu klasörler ve root dosyalar checkout edilir
ls
# apps/  packages/  package.json  turbo.json  ...

ls apps/
# frontend/  (backend, mobile, admin YOK)

ls packages/
# ui/  (utils, config YOK)
# Klasör ekleme
git sparse-checkout add packages/utils

# Mevcut ayarı görüntüleme
git sparse-checkout list
# apps/frontend
# packages/ui
# packages/utils

# Sparse checkout'u kaldır (tüm dosyaları geri getir)
git sparse-checkout disable

Cone Mode vs Non-Cone Mode

# Cone mode (önerilen — daha hızlı)
git sparse-checkout init --cone
git sparse-checkout set apps/frontend
# Klasör bazlı çalışır, her şeyi dahil veya hariç tutar

# Non-cone mode (eski yöntem — pattern bazlı)
git sparse-checkout init --no-cone
echo "/*" > .git/info/sparse-checkout
echo "!/apps/backend/" >> .git/info/sparse-checkout
echo "!/infrastructure/" >> .git/info/sparse-checkout
# Gitignore benzeri pattern'ler kullanır

Blobless + Sparse = En Hızlı

# Devasa monorepo'da sadece kendi klasörünüzle çalışma:
git clone \
  --filter=blob:none \
  --sparse \
  https://github.com/acme/mega-monorepo.git

cd mega-monorepo
git sparse-checkout set apps/frontend packages/ui

# Sonuç:
# - Tüm commit geçmişi var (log, blame çalışır)
# - Sadece ihtiyacınız olan dosyalar indirildi
# - Disk kullanımı: 100MB (tam clone: 10GB)

Commit Graph — Log ve Merge Hızlandırma

Commit Graph Nedir?

Commit graph, commit ilişkilerini (parent-child) optimize edilmiş bir binary dosyada saklar. Bu sayede git log, git merge-base ve benzeri komutlar çok daha hızlı çalışır.

Commit Graph olmadan:
  git log --oneline: her commit object'i açılır → yavaş

Commit Graph ile:
  git log --oneline: binary index'ten okunur → hızlı

Hız farkı (100K+ commit):
  Olmadan: git log --oneline  → 2-5 saniye
  İle:     git log --oneline  → 0.1-0.3 saniye
# Commit graph oluştur
git commit-graph write --reachable

# Commit graph ile birlikte generation number ve bloom filter
git commit-graph write --reachable --changed-paths

# Otomatik güncelleme (her fetch'te)
git config fetch.writeCommitGraph true

Bloom Filter — Path Bazlı Log Hızlandırma

# Belirli dosyanın geçmişini arama
git log -- src/api/handler.js

# Bloom filter olmadan: HER commit'e bakılır → yavaş
# Bloom filter ile: sadece ilgili commit'ler taranır → hızlı

# Bloom filter oluştur
git commit-graph write --reachable --changed-paths

git maintenance — Otomatik Bakım

Git 2.29+ ile gelen otomatik bakım sistemi:

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

# Bu arka planda çalışır:
# Her saat:   prefetch (remote'dan fetch, ama branch'leri güncelleme)
# Her gün:    loose-objects (pack), incremental-repack
# Her hafta:  pack-refs

# Manuel bakım görevleri
git maintenance run --task=gc
git maintenance run --task=commit-graph
git maintenance run --task=prefetch
git maintenance run --task=loose-objects
git maintenance run --task=incremental-repack
git maintenance run --task=pack-refs

# Bakımı durdur
git maintenance stop

Maintenance Konfigürasyonu

# ~/.gitconfig
[maintenance]
    auto = true
    strategy = incremental

# Cron job olarak da çalışabilir
git maintenance start
# → Sisteme cron/launchd/Task Scheduler görevi ekler

Scalar — Microsoft'un Performans Aracı

Scalar Nedir?

Microsoft'un Windows repo'su (300GB+) için geliştirdiği performans aracı. Git 2.38+ ile Git'e dahil edildi:

# Scalar ile optimized clone
scalar clone https://github.com/acme/huge-repo.git

# Bu komut şunları otomatik yapar:
# ✅ Partial clone (blobless)
# ✅ Sparse checkout
# ✅ Commit graph
# ✅ git maintenance (arka plan)
# ✅ Filesystem monitor
# ✅ Multi-pack index

# Mevcut repo'yu scalar ile optimize et
scalar register

Scalar vs Manuel Optimizasyon

Ne yapılır?                │ Manuel         │ scalar clone
───────────────────────────┼────────────────┼──────────────
Blobless clone             │ --filter=...   │ ✅ Otomatik
Sparse checkout            │ Manuel ayar    │ ✅ Otomatik
Commit graph               │ Manuel oluştur │ ✅ Otomatik
Background maintenance     │ Manuel başlat  │ ✅ Otomatik
Filesystem monitor (FSMon) │ Manuel ayar    │ ✅ Otomatik
Prefetch                   │ Manuel         │ ✅ Otomatik

Filesystem Monitor — Status Hızlandırma

git status komutu, working directory'deki tüm dosyaları tarar. 100K+ dosya varsa bu yavaş olur. Filesystem monitor (FSMonitor), işletim sisteminin dosya değişiklik bildirimlerini kullanarak sadece değişen dosyaları kontrol eder:

# FSMonitor'ı aktifleştir
git config core.fsmonitor true
git config core.untrackedcache true

# Windows'ta: Git for Windows ile birlikte gelir
# macOS: watchman kullanılır (brew install watchman)
# Linux: inotify tabanlı (Git 2.37+ yerleşik)

# Hız farkı (100K dosyalı repo):
# FSMonitor olmadan: git status → 3-5 saniye
# FSMonitor ile:     git status → 0.1-0.3 saniye

Performans Kontrol Listesi

# Büyük repo performans optimizasyonu adımları:

# 1. Clone optimizasyonu
git clone --filter=blob:none repo-url        # Blobless clone
# veya
scalar clone repo-url                         # Her şey otomatik

# 2. Sparse checkout (monorepo'da)
git sparse-checkout init --cone
git sparse-checkout set my-project/

# 3. Commit graph
git commit-graph write --reachable --changed-paths
git config fetch.writeCommitGraph true

# 4. FSMonitor
git config core.fsmonitor true
git config core.untrackedcache true

# 5. Otomatik bakım
git maintenance start

# 6. Fetch optimizasyonu
git config fetch.parallel 4                   # Paralel fetch
git config fetch.prune true                   # Stale ref temizliği

# 7. Index optimizasyonu  
git config index.threads true                 # Multi-thread index
git config feature.manyFiles true             # Çok dosya optimizasyonu

Gerçek Dünya Senaryosu: Monorepo Performansı

# Durum: 50GB monorepo, 200K dosya, 500K commit
# Normal clone: 45 dakika, 50GB disk

# Optimized workflow:

# 1. İlk kurulum (bir kez)
git clone \
  --filter=blob:none \
  --sparse \
  https://github.com/megacorp/monorepo.git

cd monorepo
git sparse-checkout set apps/my-service packages/shared

# İndirilen: ~500MB (50GB yerine!)
# Süre: ~2 dakika (45 dk yerine!)

# 2. Günlük kullanım
git status    # 0.2s (FSMonitor ile)
git log       # 0.1s (commit-graph ile)
git fetch     # 3s (prefetch ile arka planda zaten çekilmiş)
git checkout  # 1s (sadece sparse dosyalar)

# 3. Başka bir klasöre geçiş gerekirse
git sparse-checkout add apps/other-service
# Sadece o klasörün blob'ları indirilir

# 4. CI/CD'de
git clone --depth=1 --filter=blob:none repo
# 15 saniye içinde CI başlar

Performans Ölçme

# Komut süresini ölç
GIT_TRACE_PERFORMANCE=1 git status
# ... performance trace çıktısı ...

# Detaylı trace
GIT_TRACE=1 git log --oneline -10

# Zaman ölçümü
time git log --oneline | wc -l
# real    0m0.312s
# user    0m0.280s
# sys     0m0.032s

# Repo istatistikleri
git count-objects -vH
# count: 1234
# size: 12.50 MiB
# in-pack: 567890
# size-pack: 2.30 GiB
# ...

Multi-pack Index — Packfile Optimizasyonu

Büyük repo'larda çok sayıda packfile birikir. Multi-pack index bunları tek bir index ile yönetir:

# Multi-pack index oluştur
git multi-pack-index write

# Repack ile packfile'ları birleştir
git multi-pack-index repack --batch-size=0

# Doğrula
git multi-pack-index verify

Bitmap Index — Fetch/Clone Hızlandırma

# Bitmap index oluştur (server-side genellikle otomatik)
git repack -adb

# Bitmap ile object sayma çok hızlı
git rev-list --count --use-bitmap-index --all
# Bitmap olmadan: 5s, bitmap ile: 0.1s

Yaygın Hatalar

1. CI'da Tam Clone Yapmak

# ❌ Her CI run'da 5GB indirme
- uses: actions/checkout@v4
  with:
    fetch-depth: 0  # Tüm geçmiş — gerçekten gerekli mi?

# ✅ İhtiyaca göre ayarla
- uses: actions/checkout@v4
  with:
    fetch-depth: 1  # Çoğu CI job'u için yeterli

2. Sparse Checkout'ta Bağımlılığı Unutmak

# ❌ Frontend'i checkout ettiniz ama bağımlı olduğu shared paket yok
git sparse-checkout set apps/frontend
# Build fail: Cannot find module '@acme/shared-ui'

# ✅ Bağımlılıkları da ekleyin
git sparse-checkout set apps/frontend packages/shared-ui packages/utils

3. Commit Graph Güncellememeek

# ❌ Commit graph oluşturdunuz ama güncellemediniz
git commit-graph write --reachable
# ... 1000 commit sonra graph eski, yavaşlama geri geldi

# ✅ Otomatik güncelleme açın
git config fetch.writeCommitGraph true
# veya
git maintenance start  # Otomatik günceller

Özet

Bu derste büyük repo'ların performans optimizasyonunu öğrendik:

  • 📦 Partial clone--filter=blob:none ile sadece ihtiyacı indirme

  • 🏊 Shallow clone--depth=1 ile sığ geçmiş, CI için ideal

  • 📁 Sparse checkout — monorepo'da sadece kendi klasörünüzü checkout

  • 📊 Commit graph — log ve merge-base işlemlerini dramatik hızlandırma

  • 🔄 git maintenance — otomatik arka plan bakımı

  • 🚀 Scalar — Microsoft'un all-in-one performans aracı

  • 👁️ FSMonitorgit status hızlandırma, dosya izleme

  • Kombinasyon — blobless + sparse + commit-graph = en hızlı deneyim


Performans Özeti — Hızlı Referans

# Hızlı performans boost (mevcut repo için)
git config core.fsmonitor true           # Status hızlandır
git config core.untrackedcache true      # Untracked cache
git config fetch.writeCommitGraph true   # Log hızlandır  
git config fetch.parallel 4             # Paralel fetch
git config fetch.prune true             # Stale temizlik
git commit-graph write --reachable --changed-paths
git maintenance start                    # Otomatik bakım

💡 Son İpucu: Performans sorunlarını ölçmeden optimizasyon yapmayın. GIT_TRACE_PERFORMANCE=1 git status ile hangi adımın yavaş olduğunu tespit edin, sonra hedefli optimizasyon yapın. Premature optimization, hem Git'te hem kodda zaman kaybıdır.

Bir sonraki bölümde gerçek dünya ve kariyer konularına geçiyoruz: açık kaynak katkı, portföy, workflow karşılaştırma ve mülakat hazırlığı.