Git LFS
Giriş — Kütüphane ve Depo Analojisi
Bir kütüphane düşünün. Raflarda kitaplar var — metin dosyaları, hafif, taşınması kolay. Ama kütüphanenin aynı zamanda bir harita koleksiyonu var: dev boyutlu, rulo halinde, ağır, her seferinde açılması zahmetli haritalar. Bu haritaları kitaplarla aynı raflarda saklamak mantıksız — yer kaplar, erişimi zorlaştırır.
Çözüm? Haritaları ayrı bir depoda saklayın. Rafa sadece "Harita #42 — Osmanlı İmparatorluğu Yol Haritası, Depo B, Raf 7" yazan bir kart koyun. İhtiyacınız olduğunda depoya gidin ve alın.
Git LFS (Large File Storage) tam olarak bu prensibi Git'e uygular. Büyük dosyalar (resimler, videolar, veri setleri, binary'ler) ayrı bir depoda saklanır. Git repository'sinde sadece hafif bir "pointer" (referans kartı) tutulur.
Git Neden Büyük Dosyalarla Kötü?
Git'in Doğası
Git, her commit'te değişen dosyaların tam kopyasını saklar. Metin dosyaları için bu sorun değil — diff (fark) hesaplanabilir ve delta compression ile verimli depolanır. Ama binary dosyalar için bu bir felaket:
Metin dosyası (app.js — 50KB):
Commit 1: 50KB (tam kopya)
Commit 2: +2KB (sadece diff saklanır)
Commit 3: +1KB (sadece diff saklanır)
Toplam: ~53KB ✅
Binary dosya (logo.psd — 50MB):
Commit 1: 50MB (tam kopya)
Commit 2: 50MB (1 piksel değişti ama TAM KOPYA!)
Commit 3: 50MB (TAM KOPYA!)
Toplam: ~150MB ❌Repo Boyutu Karşılaştırması (10 commit sonra):
Metin dosyaları:
▓▓▓░░░░░░░░░░░░░░░░░ ~2MB
Binary dosyalar (LFS yok):
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ~500MB
Binary dosyalar (LFS ile):
▓▓▓░░░░░░░░░░░░░░░░░ ~2MB (pointer'lar)
+ LFS server'da ayrı: ~500MB (ama sadece ihtiyaç olan çekilir)Git LFS Nasıl Çözüyor?
Git LFS Çalışma Prensibi:
git add logo.psd
│
▼
LFS intercept eder
│
├──► logo.psd (50MB) → LFS server'a yükle
│
└──► Git'e pointer dosyası ekle (< 1KB)
┌─────────────────────────────────┐
│ version https://git-lfs.github │
│ .com/spec/v1 │
│ oid sha256:abc123def456... │
│ size 52428800 │
└─────────────────────────────────┘
git checkout (veya clone)
│
▼
LFS pointer'ı görür
│
└──► LFS server'dan gerçek dosyayı indir
logo.psd (50MB) → working directory'ye koyGit LFS Kurulumu
Yükleme
# macOS
brew install git-lfs
# Ubuntu/Debian
sudo apt install git-lfs
# Windows (Git for Windows ile birlikte gelir)
# veya: https://git-lfs.github.com
# Doğrula
git lfs version
# git-lfs/3.5.1 (GitHub; linux amd64; go 1.22.0)
# Global hook'ları kur (bir kez yapılır)
git lfs install
# Updated git hooks.
# Git LFS initialized.Repository'de LFS Aktifleştirme
# Yeni repo'da
git init my-project
cd my-project
git lfs install
# Mevcut repo'da
cd my-existing-repo
git lfs installDosya Tracking — Hangi Dosyalar LFS'te?
.gitattributes ile Tracking
# Dosya türlerini LFS ile izle
git lfs track "*.psd"
git lfs track "*.png"
git lfs track "*.jpg"
git lfs track "*.mp4"
git lfs track "*.zip"
git lfs track "*.exe"
git lfs track "*.dll"
git lfs track "*.so"
git lfs track "*.dylib"
# Belirli klasörlerdeki tüm dosyaları izle
git lfs track "assets/videos/**"
git lfs track "data/models/**"
# .gitattributes dosyası güncellendi
cat .gitattributes# .gitattributes içeriği:
*.psd filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.exe filter=lfs diff=lfs merge=lfs -text
assets/videos/** filter=lfs diff=lfs merge=lfs -text⚠️ Dikkat:
.gitattributesdosyasını mutlaka commit edin! Bu dosya olmadan diğer geliştiriciler LFS tracking'i göremez ve büyük dosyalar normal Git'e commit edilir.
# .gitattributes'ü commit et
git add .gitattributes
git commit -m "chore: configure Git LFS tracking"Tracking Bilgisi
# Hangi dosya türleri izleniyor?
git lfs track
# Listing tracked patterns
# *.psd (.gitattributes)
# *.png (.gitattributes)
# *.mp4 (.gitattributes)
# Tracking'i kaldır
git lfs untrack "*.exe"LFS ile Günlük Workflow
Normal Git Workflow'u ile Aynı
LFS'in güzelliği: kurulum sonrası normal Git komutlarını kullanırsınız. LFS arka planda çalışır:
# Dosya ekle (LFS otomatik devreye girer)
cp ~/design/logo.psd assets/
git add assets/logo.psd
git commit -m "feat: add project logo"
git push origin main
# Çıktıda LFS göstergesi:
# Uploading LFS objects: 100% (1/1), 52 MB | 5.2 MB/s, done.# Clone (LFS dosyaları otomatik indirilir)
git clone https://github.com/acme/my-project.git
# Downloading LFS objects: 100% (15/15), 340 MB | 10 MB/s, done.
# Sadece pointer'ları çek (büyük dosyaları indirme)
GIT_LFS_SKIP_SMUDGE=1 git clone https://github.com/acme/my-project.git
# veya
git clone --filter=blob:none https://github.com/acme/my-project.git
# Sonra ihtiyaç olan dosyaları çek
git lfs pull
# veya belirli dosyaları
git lfs pull --include="assets/logo.psd"LFS Dosyalarını Listeleme
# Repo'daki LFS dosyalarını listele
git lfs ls-files
# abc123def4 * assets/logo.psd
# def456ghi7 * assets/banner.png
# ghi789jkl0 * data/model.bin
# Detaylı bilgi
git lfs ls-files --longPointer Dosyasını İnceleme
# Pointer dosyasının içeriği
git show HEAD:assets/logo.psd
# version https://git-lfs.github.com/spec/v1
# oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393
# size 52428800
# Gerçek dosya mı pointer mı kontrol et
git lfs pointer --check assets/logo.psd.gitattributes Detaylı Konfigürasyon
.gitattributes dosyası sadece LFS için değil, birçok Git davranışını kontrol eder:
# .gitattributes tam örnek
# === LFS Tracking ===
*.psd filter=lfs diff=lfs merge=lfs -text
*.ai filter=lfs diff=lfs merge=lfs -text
*.sketch filter=lfs diff=lfs merge=lfs -text
*.fig filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.tar.gz filter=lfs diff=lfs merge=lfs -text
*.woff2 filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
*.pkl filter=lfs diff=lfs merge=lfs -text
*.h5 filter=lfs diff=lfs merge=lfs -text
*.model filter=lfs diff=lfs merge=lfs -text
# === Line Endings ===
# Tüm metin dosyalarında otomatik satır sonu dönüşümü
* text=auto
# Belirli dosyalar her zaman LF
*.sh text eol=lf
*.bash text eol=lf
Makefile text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
# Belirli dosyalar her zaman CRLF (Windows)
*.bat text eol=crlf
*.cmd text eol=crlf
# === Merge Stratejileri ===
# Lock dosyalarını merge etme
package-lock.json merge=ours
yarn.lock merge=ours
# === Diff/Merge Dışı Tutma ===
*.min.js -diff
*.min.css -diff
# === Linguist (GitHub dil istatistikleri) ===
docs/* linguist-documentation
vendor/* linguist-vendored
*.generated.ts linguist-generatedLine Endings Problemi
Windows (CRLF) ve Unix (LF) arasındaki satır sonu farkı, ekip çalışmasında sık sorun yaratır:
# Önerilen ayar (tüm platformlarda tutarlı)
git config --global core.autocrlf input # macOS/Linux
git config --global core.autocrlf true # Windows
# .gitattributes ile (repo seviyesinde — daha iyi)
* text=autoLFS ile CI/CD
GitHub Actions'da LFS
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
lfs: true # LFS dosyalarını da çek
# veya sadece ihtiyaç olan dosyaları
- uses: actions/checkout@v4
with:
lfs: false
- run: git lfs pull --include="assets/critical/**"LFS Bandwidth Yönetimi
GitHub LFS'in ücretsiz katmanında sınırlı bandwidth vardır:
GitHub LFS Limitleri:
───────────────────────
Free: 1 GB storage, 1 GB bandwidth/ay
Data Pack: 50 GB storage, 50 GB bandwidth/ay ($5/ay)
Bandwidth tasarrufu:
• CI'da sadece ihtiyaç olan LFS dosyalarını çekin
• GIT_LFS_SKIP_SMUDGE=1 ile gereksiz indirmeleri önleyin
• LFS dosyalarını cache'leyin (Actions cache)# LFS cache ile bandwidth tasarrufu
- name: Cache LFS files
uses: actions/cache@v4
with:
path: .git/lfs
key: lfs-${{ hashFiles('.lfs-assets-id') }}
restore-keys: lfs-
- uses: actions/checkout@v4
with:
lfs: trueMevcut Repo'ya LFS Ekleme (Migration)
Zaten büyük dosyalar commit edilmiş bir repo'ya LFS eklemek:
# 1. LFS kurulumu
git lfs install
# 2. Tracking ayarla
git lfs track "*.psd"
git lfs track "*.png"
# 3. Mevcut dosyaları LFS'e taşı (geçmişi de dahil)
git lfs migrate import \
--include="*.psd,*.png" \
--everything
# Bu komut:
# - Tüm branch'lerde belirtilen dosyaları LFS pointer'larına çevirir
# - Commit SHA'ları değişir (history rewrite)
# - Force push gerekir# Sadece belirli branch'lerde migrate
git lfs migrate import \
--include="*.psd" \
--include-ref=refs/heads/main \
--include-ref=refs/heads/develop
# Dry run (ne olacağını gör, uygulamadan)
git lfs migrate info --include="*.psd,*.png,*.mp4"
# migrate: Sorting commits: ..., done.
# migrate: Examining commits: 100% (450/450), done.
# *.psd 524 MB 15 files
# *.png 120 MB 234 files
# *.mp4 1.2 GB 3 files
# Migrate sonrası force push
git push --force --all
git push --force --tags⚠️ Dikkat:
git lfs migrate importhistory rewrite yapar. Tüm commit SHA'ları değişir. Ekibin yeniden clone yapması gerekir. Bu işlemi paylaşılmış branch'lerde yapmadan önce ekiple koordine edin.
LFS Lock — Dosya Kilitleme
Binary dosyalarda merge conflict çözümü neredeyse imkânsızdır. İki tasarımcı aynı PSD dosyasını aynı anda düzenlerse, birinin çalışması kaybolur. LFS lock, bu sorunu "aynı anda sadece bir kişi düzenleyebilir" kuralıyla çözer:
# Dosyayı kilitle
git lfs lock assets/main-banner.psd
# Locked assets/main-banner.psd
# Kilitli dosyaları listele
git lfs locks
# ID Path Owner Locked At
# 1234 assets/main-banner.psd ahmet 2024-01-15T10:00:00Z
# Kilit kaldır
git lfs unlock assets/main-banner.psd
# Başkasının kilidini kaldır (force — dikkatli kullanın)
git lfs unlock assets/main-banner.psd --force# Kilidi olan dosyayı düzenlemeye çalışırsa:
$ git push origin main
# Lock denied: assets/main-banner.psd is locked by ahmetLFS Server Seçenekleri
GitHub dışında kendi LFS server'ınızı da barındırabilirsiniz:
LFS Server Seçenekleri:
───────────────────────────────────
GitHub LFS → Entegre, 1GB ücretsiz
GitLab LFS → Entegre, 10GB ücretsiz
Gitea LFS → Self-hosted, sınırsız
lfs-server (Go) → Self-hosted, minimal
S3-backed → AWS S3 + lfs-s3 proxyLFS Alternatifleri
Çözüm │ Ne Zaman?
───────────────┼────────────────────────────────────
Git LFS │ Orta büyüklükte binary'ler (<1GB), GitHub entegrasyon
.gitignore │ Build artifact'ları, geçici dosyalar (hiç commit etme)
Cloud Storage │ Çok büyük dosyalar (>1GB), veri setleri → S3, GCS
DVC │ ML model ve veri seti versiyonlama
Artifact Mgmt │ Build output → Artifactory, NexusDVC (Data Version Control) — ML İçin
Machine learning projelerinde veri setleri ve model dosyaları çok büyük olabilir (GB-TB seviyesinde). DVC, Git LFS'in ML için özelleştirilmiş hali gibidir:
# DVC kurulum
pip install dvc
# S3 backend ile
dvc init
dvc remote add -d storage s3://my-bucket/dvc
# Büyük veri setini takip et
dvc add data/training-set.csv # 10GB dosya
git add data/training-set.csv.dvc data/.gitignore
git commit -m "feat: add training dataset"
dvc push # S3'e yükle
# Başka bir makine'de
git clone repo
dvc pull # S3'den indirLFS Performans ve Troubleshooting
LFS Hızlandırma
# Paralel download (büyük dosyalarda faydalı)
git config lfs.concurrenttransfers 8
# Batch transfer aktifleştir
git config lfs.batch true
# Transfer timeout ayarla
git config lfs.activitytimeout 60
# Yavaş bağlantılarda transfer süresini uzat
git config lfs.transfermaxretries 5LFS Durumunu Kontrol Etme
# LFS ortamını doğrula
git lfs env
# Endpoint: https://github.com/acme/repo.git/info/lfs (auth=basic)
# LocalMediaDir: /home/user/repo/.git/lfs/objects
# LocalReferenceDirs:
# ConcurrentTransfers: 8
# TusTransfers: true
# BasicTransfersOnly: false
# LFS nesnelerini doğrula (bütünlük kontrolü)
git lfs fsck
# Checking objects:
# ✓ abc123def456 (ok)
# ✓ def789abc012 (ok)
# All 15 objects verified OK
# Belirli bir dosyanın LFS durumunu kontrol et
git lfs status
# Objects to be pushed:
# assets/logo.psd (LFS: abc123 -> def456)
# Objects to be committed:
# assets/banner.png (LFS: new file)LFS Depolama Temizleme
LFS cache zamanla büyüyebilir:
# LFS cache boyutunu kontrol et
du -sh .git/lfs/
# Artık gerekmeyen LFS nesnelerini temizle
git lfs prune
# ✓ Pruning 23 unreferenced objects
# ✓ Deleted 23 files (128 MB)
# Dry run (ne silineceğini gör)
git lfs prune --dry-run
# 23 files would be pruned (128 MB)
# Daha agresif temizlik
# Sadece en son commit'teki dosyaları tut
git lfs prune --recentLFS ile Tasarım Dosyaları Workflow'u
Tasarım ekipleriyle çalışırken LFS özellikle önemlidir:
Tipik Tasarım Workflow:
1. Tasarımcı → PSD/Figma export'u yapar
2. git lfs lock banner.psd → Dosyayı kilitle
3. PSD'yi düzenle
4. git add → git commit → git push
5. git lfs unlock banner.psd → Kilidi aç
Neden lock?
→ PSD merge edilemez (binary)
→ İki kişi aynı anda düzenlerse biri kaybolur
→ Lock, "ben çalışıyorum" sinyali verir# Tasarım branch workflow örneği
$ git checkout -b design/homepage-redesign
$ git lfs lock assets/homepage-hero.psd
Locked assets/homepage-hero.psd
# Tasarım çalışması...
$ git add assets/homepage-hero.psd
$ git commit -m "design: Update homepage hero banner"
$ git push origin design/homepage-redesign
# PR açıldı ve merge edildi
$ git lfs unlock assets/homepage-hero.psd
Unlocked assets/homepage-hero.psdLFS ve Large Repo Best Practices
Git LFS Karar Ağacı:
Dosya türü ne?
├── Kaynak kod (.js, .py, .java) → Normal Git ✅
├── Küçük asset (<1MB, .svg, .json) → Normal Git ✅
├── Orta asset (1-50MB, .png, .jpg) → Git LFS ✅
├── Büyük asset (50-500MB, .psd, .mp4) → Git LFS ✅
├── Çok büyük (>500MB, dataset) → Cloud storage (S3) ✅
└── Build artifact (.jar, .exe) → .gitignore ✅
Genel kurallar:
• 10MB üzeri binary dosyalar → LFS düşün
• 100MB üzeri → kesinlikle LFS veya .gitignore
• Text dosyaları → Normal Git (diff çalışır)
• Sık değişen büyük binary → LFS + lockYaygın Hatalar
1. .gitattributes Commit Etmemek
# ❌ LFS tracking ayarladınız ama .gitattributes commit etmediniz
git lfs track "*.psd"
git add assets/logo.psd
git commit -m "add logo"
# .gitattributes commit edilmedi → diğer geliştiriciler LFS kullanmaz!
# ✅ Önce .gitattributes'ü commit edin
git lfs track "*.psd"
git add .gitattributes
git commit -m "chore: configure LFS for PSD files"
git add assets/logo.psd
git commit -m "feat: add logo"2. LFS Olmadan Büyük Dosya Push Etmek
# ❌ GitHub'ın 100MB dosya limiti
git push origin main
# remote: error: File data.zip is 150.00 MB; this exceeds GitHub's limit of 100.00 MB
# ✅ Önce LFS ile track edin
git lfs track "*.zip"
git add .gitattributes
git reset HEAD data.zip
git add data.zip # Şimdi LFS üzerinden
git commit --amend
git push3. CI'da LFS Dosyalarını Çekmemek
# ❌ LFS dosyaları eksik
- uses: actions/checkout@v4
# LFS dosyaları pointer olarak kalır → testler fail olur
# ✅ LFS'i aktif et
- uses: actions/checkout@v4
with:
lfs: trueÖzet
Bu derste Git LFS ile büyük dosya yönetimini öğrendik:
📦 Git LFS — büyük dosyaları ayrı server'da sakla, repo'da pointer tut
📋 .gitattributes — hangi dosyaların LFS'te olacağını belirle (tracking)
🔄 Normal workflow —
git add/commit/pushaynı, LFS arka planda çalışır🔀 Migration — mevcut repo'daki büyük dosyaları LFS'e taşıma
🔒 File locking — binary dosyalarda aynı anda tek kişi düzenleme
📁 .gitattributes — LFS dışında line endings, merge stratejisi, linguist
🤖 CI/CD —
lfs: trueile Actions'da LFS desteği, cache ile bandwidth tasarrufu
💡 Son İpucu: Git LFS'in en büyük avantajı şeffaflık. Kurulum yaptıktan sonra
git add,git commit,git push— her şey normal Git workflow'u ile aynı. LFS arka planda sessizce çalışır. Ekibe sadece.gitattributes'ün repo'da olduğundan ve herkesingit lfs installçalıştırdığından emin olun.
Bir sonraki derste Git'in ileri düzey komutlarını öğreneceğiz: reflog ile kayıp commit kurtarma, git fsck ile repo sağlık kontrolü ve dangling objects.
AI Asistan
Sorularını yanıtlamaya hazır