Git’te büyük dosyaların geleceği yine Git’in kendisi
(tylercipriani.com)- Git projesi kısa süre önce büyük dosya yönetimi sorununu doğrudan çözmeye resmen başladı
- Git LFS, kullanıcılar için çeşitli maliyetler ve vendor lock-in gibi sorunlar yaratan geçici bir çözüm
- Son dönemde gelen partial clone özelliği sayesinde, yalnızca Git kullanarak LFS’nin rolünün büyük kısmını ikame etmek mümkün hale geldi
- İleride large object promisor adlı yeni bir çözümün de resmi Git’e entegre edilmesi hazırlanıyor
- Bu değişimlerle birlikte, büyük dosya yönetiminin nihai çözümünün harici eklentiler değil, Git’in kendisi olması bekleniyor
Git’in büyük dosya sorunu ve değişim
- Git’in en büyük düşmanı tam da büyük dosyalar olabilir
- Büyük dosyalar Git deposunu şişirir,
git clonehızını düşürür ve çoğu hosting ortamını da olumsuz etkiler
Git LFS’nin ortaya çıkışı ve sınırları
- 2015’te GitHub, büyük dosya sorununu aşmak için Git LFS’yi yayınladı
- Ancak Git LFS de kendi başına yeni karmaşıklık ve ek depolama maliyetleri getirir
- Git topluluğu uzun süredir büyük dosya sorununu kökten nasıl çözeceğini sessizce düşünüyordu; son resmi Git sürümlerinde ise LFS olmadan büyük dosyaları yönetmeye yönelik yeni bir yön ortaya kondu
Bugün hemen uygulanabilecek yöntem: Git LFS’yi partial clone ile değiştirmek
-
partial clone’un çalışma mantığı
- Git LFS: Büyük dosyalar depo dışında tutulur ve çalışma sırasında yalnızca gerekli dosyalar indirilir
- Git partial clone (2017’de eklendi):
--filterseçeneğiyle belirli boyutun üzerindeki blob’lar hariç tutularak kopyalama yapılır- Yalnızca gerektiğinde ilgili büyük dosya sunucudan indirilir
Partial clone kullanıldığında Clone ve Fetch sırasında [büyük ikili varlıkları] önceden indirmek gerekmez; bu da indirme süresini ve disk kullanımını azaltabilir
-
partial clone ile LFS’nin ortak yönleri
- 1. Checkout boyutunu en aza indirme: Yalnızca en güncel sürüm alınır, tüm dosya geçmişi atlanır
- 2. Hızlı klonlama: Büyük dosyalar aktarılmadığı için clone daha hızlıdır
- 3. Hızlı kurulum: shallow clone’dan farklı olarak tüm proje geçmişine erişim mümkündür
-
partial clone kullanım örneği
- Geçmişinde çok sayıda büyük PNG dosyası bulunan bir repo’nun klonlama süresi ve disk kullanımı örneği:
- Normal clone ile neredeyse 4 dakika sürüyor ve 1.3GB yer kaplıyor
- partial clone ve 100KB blob sınırı uygulandığında 6 saniyede klonlanıyor ve 49MB yer kaplıyor
- Orijinale göre klonlama hızı %97 iyileşiyor, checkout boyutu %96 küçülüyor
- Geçmişinde çok sayıda büyük PNG dosyası bulunan bir repo’nun klonlama süresi ve disk kullanımı örneği:
-
partial clone’un sınırları
- Filtrelenen veriye ihtiyaç duyulduğunda (ör.
git diff,git blame,git checkout) Git sunucudan dosyayı ister - Bu, Git LFS ile aynı özelliktir
- Pratikte ikili dosyalarda
blameçalıştırma ihtiyacı nadirdir
- Filtrelenen veriye ihtiyaç duyulduğunda (ör.
Git LFS’nin sorunları
- Yüksek vendor lock-in: GitHub uygulaması yalnızca kendi sunucularını destekler; bu da ücretlendirme ve bağımlılık yaratır
- Maliyet sorunu: 50GB depolamada GitHub LFS yıllık $40, Amazon S3 ise $13
- Geri dönüşün zorluğu: Bir kez LFS’ye geçildiğinde, geçmiş yeniden yazılmadan eski hâle dönmek mümkün değildir
- Sürekli kurulum maliyeti: Tüm ekip üyelerinin LFS kurması gerekir; kurulmadığında dosya yerine metadata dosyaları görülür ve bu da kafa karışıklığı yaratır
İleriye dönük görünüm: Large Object Promisor
- Büyük dosyalar hosting platformları (GitHub, GitLab) için de maliyet sorunu yaratır
- Git LFS, büyük dosyaları CDN’e offload ederek sunucu maliyetlerini azaltır
-
Large Object Promisor nedir?
- Git bu yılın başında large object promisor adlı özelliği resmen merge etti
- Bu özellik, LFS’ye benzer şekilde sunucu tarafındaki depo yükünü azaltırken kullanıcı tarafındaki karmaşıklığı büyük ölçüde düşürür
Bu çabanın amacı, özellikle zaten ikili biçimde sıkıştırılmış büyük blob’larla ilgili sunucu tarafı işlemlerini iyileştirmektir
Git LFS’ye alternatif bir çözümdür
– Large Object Promisors, git-scm.com
-
Nasıl çalışır?
- 1. Kullanıcı büyük dosyayı Git host’una push eder
- 2. Host, büyük dosyayı arka uçtaki promisor’a offload eder
- 3. clone sırasında Git host’u istemciye promisor bilgisini verir
- 4. İstemci gerekirse ilgili promisor’dan büyük dosyayı otomatik olarak alır
-
Güncel durum ve zorluklar
- Büyük nesne promisor’u hâlâ geliştirme aşamasında; Mart 2025’te kodun bir kısmı Git’e merge edildi
- GitLab gibi platformlarda ek implementasyonlar ve çözülmemiş konular üzerine tartışmalar sürüyor
- Yaygın kullanıma geçmesi için hâlâ zamana ihtiyaç var
- Yakın vadede büyük dosya depolamada Git LFS’ye bağımlılık kaçınılmaz görünüyor
- promisor yaygınlaştığında GitHub’a 100MB üzeri dosya yüklemek de mümkün hale gelebilir
Sonuç: Git’te büyük dosyaların geleceği Git
- Git projesi, büyük dosya sorununu sizin yerinize durmaksızın düşünüyor
- Şu anda hâlâ Git LFS kullanımı gerekiyor
- Ancak partial clone ve large object promisors geliştikçe Git LFS giderek gereksiz hale gelecek; çok yakında büyük dosyaları yalnızca Git ile kolayca yönetmek mümkün olacak
- Gelecekte MP3 kütüphanesini Git’e koyma fikrinin kendisi, büyük ölçekli kullanımın önündeki son engel olabilir
1 yorum
Hacker News görüşleri
Eskiden svn bile, çok sayıda büyük ikili dosya içeren 150GB’lık bir çalışma dizininde büyük sorunlar olmadan gayet iyi çalışıyordu; buna karşılık git böyle değil. svn’in büyük ikili dosyalar konusunda neden git’ten farklı bir yaklaşım izlediğini, git’in neden aynı şeyi yapamadığını merak ediyorum. Ayrıca ikili verilerle çalışırken mutlaka gereken özellik dosya kilitlemedir; belirli bir dosyada yalnızca bir kişinin çalışıp diğerlerinin salt okunur olması, karmaşık merge sorunlarını önleyebilir. Büyük dosyaları dışarıya offload etmenin gerçek performans ya da kararlılık sorunlarını gerçekten iyileştirip iyileştirmediğini de pek anlayamıyorum. Sonuçta depo farklı olsa da yine depodur. Offload işi aslında public git forge’ların büyük dosya depolama maliyetinden kaçınma yöntemi gibi görünüyor
Large object promisor kavramı hoşuma gidiyor. S3 gibi bir yere kolayca bağlayıp kullanmak mümkün olursa mevcut LFS’ten hemen geçerim gibi geliyor. S3, büyük ikili dosyaları sürüm kontrolünde tutarken iyi bir sinerji sağlıyor. Intelligent Tiering sayesinde veri yaşlandıkça otomatik olarak daha ucuz depolama katmanlarına taşınması da avantaj. 10 yıllık veriyi geri yüklemek yarım gün sürse bile sorun değil
Ben de aynı fikirdeyim. Bunun neden en başından beri varsayılan yöntem olmadığını anlayamıyorum. Küçük bir git LFS sunucusunu kendim işletiyorum ve git yalnızca S3’ü native desteklese hemen geçmeye hazırım
Şu an iş yerinde maliyeti düşürmek için LFS nesnelerini bucket’ta cache’liyoruz. Her PR çalıştırıldığında
git lfs ls-filesile dosya listesini alıyor, gcp’den çekiyor,git lfs checkoutile nesneleri lokalde saklıyor, sonrapullile yalnızca eksik kalanları alıyoruz. Cache’lenmemiş dosyalargcloud storage rsyncile tekrar bucket’a yükleniyor. Geliştirici açısından ek ayar gerekmiyor; sadece yeni nesneler pull ediliyor ve GitHub UI da depo durumu konusunda kafa karıştırmıyor. Eskiden LFS backend’i kendimiz mi kursak diye düşünmüştüm ama bu yöntem şu anki en büyük sorunumuzu çözüyor. GitHub, CI sırasında LFS dosyaları her alındığında aşırı trafik ücreti çıkarıyordu; ayrıca 10GB cache sınırı ve branch’ler arasında paylaşım olmaması nedeniyle her seferinde yeniden indirmek gerekiyordu. Cache kapasitesini para verip artırmak isterdim ama bunun da bir yolu yoktu. Bunu geliştiricilere uygulamak da yalnızca bir git hook eklemek kadar basitS3’ün Amazon’la ilgili bir servis olup olmadığını merak ediyorum
Git LFS hakkında çeşitli olumsuz noktalardan söz edilse de vendor lock-in olduğu görüşüne katılmıyorum. GitHub açık istemci ve sunucu sağladığı için bu iddia haksız. Yine de LFS, offline/sneakernet kullanımında çalışmıyor; bu yaygın bir durum olmasa da anılmaya değer. large object promisor, LFS’nin istemci tarafı karmaşıklığını sunucuya taşımış gibi görünüyor; sonuçta sadece karmaşıklığın yeri değişmiş oluyor. Eğer yapı, git sunucusunun dosyaları LFS sunucusuna ve nesne deposuna yüklemesi şeklindeyse farklı trade-off’lar ortaya çıkar. Public git sunucularında promisor remote gizli tutulursa upload sırasında ne olacağını merak ediyorum
Bence LFS gerçekten kötü. Sunucu implementasyonu da dağınık ve nesne içeriğiyle depolama yöntemini birbirine karıştırıyor. Opt-in yöntemi de çok kötü; düşünmeden kullanırsan aslında istediğin dosya yerine sadece küçük bir metin dosyası elde ediyorsun. Yeni çözümün daha iyi olup olmadığını bilmiyorum ama LFS’nin iyi olmadığı açık
Yakın zamanda öğrendiğim başka bir Git LFS sorunu da, migration’ın üst commit’lerdeki
.gitattributesdosyalarını da kirletmesi. Yani commit sırası A→B→C ise ve büyük dosya yalnızca C’de LFS’ye eklendiyse, A ve B’de de var olmayan LFS dosyalarına işaret eden.gitattributesoluşuyor. Çünkü migration sırasında.gitattributes, geçmiş boyunca geriye doğru yayılıyor ve mevcut commit’te dosyanın gerçekten var olup olmadığına bakmıyorEskiden Git LFS SSH desteklemiyordu; bu yüzden mutlaka SSL sertifikası almak gerekiyordu ve bu da evde self-host eden kullanıcılar için giriş bariyeriydi. GitLab yakın zamanda SSH desteği yaması eklemiş gibi görünüyor
Yazılım mühendisliği dersinde, büyük dosyaları (medya vb.) Git’e koymak yerine artifact deposuna (Artifactory vb.) koymamız önerilmişti. Böylece snapshot dependency biçiminde dağıtılabilir ve build sistemi yalnızca en güncel sürümü alacak şekilde yönetilebilir. Ekip arkadaşlarının lokalde biriken eski dosyaları da build sistemi cache’ini temizleyerek hemen kaldırılabilir
Bu yaklaşım biraz git submodule gibi duruyor. Eğer submodule bu sorunu çözseydi insanlar zaten kullanırdı. git submodule da shallow clone destekliyor (ilgili bağlantı: https://stackoverflow.com/questions/2144406/how-to-make-shallow-git-submodules). Ben büyük dosya sorununu hiç yaşamadım; bu yöntem neden işe yaramıyor olabilir merak ediyorum. SO’daki dezavantajlar bana çok büyük görünmüyor
Derste CI/CD sistem mimarisinin de öğretilip öğretilmediğini merak ediyorum. Günümüzde yeni mühendisler GitLab, Artifactory, CodeSonar, Anchore gibi araçlarla entegre çalışan genel yapıya pek hakim değil
Bu yöntemin de dezavantajları var. CI/CD sistemi ya da geliştiriciler için ek kimlik bilgileri gerekiyor. Commit süreci de birden çok adıma çıkıyor; önce artifact ID’yi bilmek gerekiyor ve bunu otomatikleştirmek için git hook kullanmaya başlayınca sonunda git-lfs kadar karmaşık hale geliyor
Bu yazı LFS’yi haksız değerlendiriyor. LFS, GitHub’a bağımlı değil ve protokolü de açık. LFS’nin dezavantajları, git eklentisi olmasının kaçınılmaz sonucu; promisor’lar da aslında LFS ile aynı fikir. Sadece git’in içine gömülünce UX biraz daha iyi oluyor
Bu gerçek çözüm değil. git LFS de sadece geçici bir çözüm ve clone sırasında filtre argümanı vermek de temel sorunu çözmüyor.
git clone, her kullanıcının öğrendiği ilk komutlardan biri; ama burada her seferinde filtreyi hatırlamak gerekiyor. Unutulursa sadece zaman kaybediliyor, doğru yapılsa bile clone edilen depo düzgün çalışmayabilir. Sonuçta rsync gibi en güncel dosyaları önce verimli şekilde alan bir yapıya geçmek gerekiyor ki sorun kökten çözülsün. git bu tür köklü değişiklikleri pek yapmıyorKesinlikle katılıyorum. git sorunları hep bir flag daha ekleyerek “çözüyor”, ama kullanıcıların çoğu bu özelliklerin farkında bile değil. Varsayılanları iyileştirmek, uyumluluğu bozmadan da bu sorunları çözebilir
Eğer depo boyutunun çoğu geçmiş revizyonlardaysa, rsync benzeri şekilde önce yalnızca en güncel sürümü almak çoğu kullanıcı için en uygun çözüm olur
Git çekirdeğine büyük dosya desteği eklenmesine çok seviniyorum. Dış çözüm olsa bile sonuçta yine benzer bir opt-in yapısı ortaya çıkıyor. Komut sayısını olabildiğince azaltıp süreci seamless hale getirmek istediğim için API’yi
.gitattributesdosyasındaki smudge/clean filtreleriyle sınırlı tasarladım. Ayrıca vendor lock-in’i ortadan kaldırmak için Atlassian ve Microsoft ile doğrudan çalıştım; dosya kilitleme API’sinde de Atlassian’dan büyük destek alındı. LFS, üç farklı host üzerinde uyumlu destek sunan açık kaynak bir çözüm olarak sağlanıyorBiz de git veya git-lfs’de yaşadığımız sorunları çözmek için
oxengeliştiriyoruz. git arayüzünü aynen korurken büyük dosyalar ve milyonlarca dosya içeren monorepo ortamlarında çok daha hızlı çalışıyor. Açık kaynak CLI ve sunucu sunuyoruz; ilgilenirseniz geri bildirim duymak isterizhttps://github.com/Oxen-AI/Oxen
git’in depolama biçiminin kendisinin de restic veya borg gibi modern yedekleme araçlarında olduğu gibi dosya ve dizinler için content-defined chunking temelli şekilde baştan ele alınması gerekiyor
GitLFS’nin eksilerinden biri olarak kimlik doğrulama sorunu da atlanmış; SSH-agent kullanılmazsa tek bir push sırasında bile birden fazla kez kimlik doğrulama gerekebiliyor. Kendi deneyimime göre bunu iki ya da üç defadan fazla yaşadığım bile oldu