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 indirmeBlobless 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 çekilirTreeless 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 gerekliBoyut 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 indirilirKarşı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:noneen 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.gitShallow 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 indirCI/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.jsonSparse 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 disableCone 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ırBlobless + 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 trueBloom 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-pathsgit 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 stopMaintenance Konfigürasyonu
# ~/.gitconfig
[maintenance]
auto = true
strategy = incremental
# Cron job olarak da çalışabilir
git maintenance start
# → Sisteme cron/launchd/Task Scheduler görevi eklerScalar — 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 registerScalar 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 │ ✅ OtomatikFilesystem 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 saniyePerformans 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 optimizasyonuGerç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şlarPerformans Ö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 verifyBitmap 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.1sYaygı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 yeterli2. 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/utils3. 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:noneile sadece ihtiyacı indirme🏊 Shallow clone —
--depth=1ile 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ı
👁️ FSMonitor —
git statushı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 statusile 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ığı.
AI Asistan
Sorularını yanıtlamaya hazır