Git aslında “deltaları çözüyor” derken ne yapıyor?


187

Bir deponun ilk klonu sırasında git önce nesneleri alır (yeterince açıktır) ve sonra aynı miktarda "deltaları çözümlemek" için harcar. Aslında klonun bu aşamasında neler oluyor?



1
Ayrıca bkz. Git 2.20 (Q4 2018) ve daha fazla delta adası için: stackoverflow.com/a/52458712/6309
VonC

Yanıtlar:


54

Git, bazı nesneleri paket dosyalarında saklamak için delta kodlaması kullanır . Ancak, her değişikliği oynatmak zorunda kalmak istemiyoruz hiç Git ayrıca sıra saklanan dosya içeriğinin ara sıra anlık sahiptir, böylece güncel sürümünü almak için belirli bir dosya üzerinde. "Deltaları çözümlemek", tüm bunların tutarlı kalmasını sağlamakla ilgili adımdır.

İşte Pro Git kitabının çevrimiçi olarak sunulan "Git Internals" bölümünden bu konuyu anlatan bir bölüm .


80
Bu cevap yanlış. Git'i değil, Mercurial'ın nasıl çalıştığını açıklıyor gibi görünüyor. Google'ın bu sorunu araması geliyor, bu yüzden cevap vermem gerektiğini hissediyorum. Git yok değil deltalar olarak kaydedilmesini arasındaki farkları saklamak; Git bir "tüm nesne" deposudur. Bu nedenle Git'in belirli bir dosyayı göstermek için "anlık görüntülere" ihtiyacı yoktur, çünkü dosya geçmişinin deltalardan yeniden yapılandırılması gerekmez. Mercurial böyle çalışır.
nexus

12
Delta kodlamasının devreye girdiği tek yer, sıkıştırma ve aktarım için olan paket dosyasındadır - Git'in dünyayı nasıl gördüğünü değiştirmez. ( kernel.org/pub/software/scm/git/docs/v1.6.2.3/technical/… ) Doğru bir yanıt için lütfen aşağıdaki araqnid'in cevabına bakınız.
nexus

4
Bu bağlamdaki tüm "anlık görüntü", delta kodlu sürüm yerine dosya durumunun tam kopyası anlamına gelir. Bahsettiğiniz gibi Git , paket dosyalarında delta kodlamasını kullanır. Kimse "Git'in dünyayı nasıl gördüğünü değiştirdiğini" söylemedi; lütfen kendi varsayımlarınızı yansıtmayı bırakın.
Amber

2
Cevabınız hala yanlış. "Git ayrıca zaman zaman saklanan dosya içeriğinin anlık görüntülerine de sahip." -- Bu doğru değil. "'Deltaları çözümlemek', bunların hepsinin tutarlı kalmasını sağlamakla ilgili adımdır." - bu da doğru değil, araqnid'in aşağıdaki cevabı doğrudur.
nexus

1
Yukarıda belirtilen bölümde açıklandığı gibi Git, en son sürümün tüm dosya içeriğini daima saklar. Önceki sürümler "gevşek" dosyalar olduklarında delta kodlu dosyalar olarak saklanır. Periyodik olarak (arayarak git gcveya Git ne zaman gerekli olduğunu belirlediğinde) Git, yer kazanmak için tüm "gevşek" dosyaları bir paket dosyasına sıkıştırır ve bu paket dosyasına bir dizin dosyası oluşturulur. Dolayısıyla zlib kendi delta algoritmasıyla sıkıştırır, ancak Git önceki sürümleri saklamak için delta kodlaması kullanır. En yaygın ve sık erişim en son sürüm olduğundan, anlık görüntü olarak saklanır.
BrionS

118

Aşamaları git clone:

  1. Repo veritabanındaki tüm nesnelerin "paket" dosyasını alma
  2. Alınan paket için bir dizin dosyası oluşturma
  3. Kafa revizyonuna göz atın (açıkça çıplak olmayan bir repo için)

"Deltaların çözümlenmesi", paket dosyasını ("git index-pack") endeksleyen ikinci aşama için gösterilen mesajdır.

Paketi dosyaları yok değil onları gerçek nesne kimlikleri, yalnızca nesne içeriğe sahip. Bu nedenle nesne kimliklerinin ne olduğunu belirlemek için git paketindeki her nesnenin bir sıkıştırmasını + SHA1 yapmak zorundadır, bu nesne daha sonra indeks dosyasına yazılır.

Bir paket dosyasındaki bir nesne delta olarak saklanabilir, yani başka bir nesnede yapılacak değişiklik dizisi. Bu durumda, git temel nesneyi almak, komutları uygulamak ve sonucu SHA1 gerekir. Temel nesnenin kendisinin bir dizi delta komutu uygulanarak türetilmesi gerekebilir. (Bir klon söz konusu olduğunda, temel nesneye zaten rastlanmış olsa da, bellekte üretilen kaç nesnenin önbelleğe alınmasının bir sınırı vardır).

Özetle, "deltaların çözümlenmesi" aşaması, şaşırtıcı bir şekilde oldukça uzun sürmeyen tüm repo veritabanının sıkıştırmasının kaldırılmasını ve denetlenmesini içerir. Büyük olasılıkla SHA1'lerin sıkıştırmasını açmak ve hesaplamak aslında delta komutlarını uygulamaktan daha fazla zaman alır.

Sonraki bir getirme durumunda, alınan paket dosyası, alıcı git'in zaten sahip olması beklenen diğer nesnelere referanslar (delta nesnesi temelleri olarak) içerebilir. Bu durumda, alıcı git, alınan paket dosyasını, bu tür başvurulan nesneleri içerecek şekilde yeniden yazar, böylece depolanan herhangi bir paket dosyası kendi kendine yeterli olur. Burası "deltaları çözümlemek" mesajının kaynaklandığı yer olabilir.


7
Bu paralelleştirilebilir mi?
brooksbp

Bu delta sıkıştırması, bir zlib veri akışında birden fazla nesne depolamaktan daha mı fazla?
fuz

1
@FUZxxl evet, iki blob'u karşılaştırmak ve bir düzenleme komut dosyası üretmek için diff veya xdelta gibi bir algoritma kullanıyor
araqnid

@brooksbp: Yalnızca sınırlamalarla. 103fa49 kimliğine sahip nesnenin kodunun çözülmesi gerekebilir, ancak 103fa49 aldığınızda, df85b51 henüz orada değildir (paket dosyaları kesinlikle sha1 karmaları tarafından sipariş edilir). Yani, sadece orada olan şeylere gönderme yapan her şey için, işler kolaydır, ancak diğer her şey için, alınana kadar beklemeniz gerekir. Ve bu delta sıkıştırma iç içe yerleştirilebilir, bu nedenle 103fa49 4e9ba42'ye ihtiyaç duyabilir, bu da 29ad945'e ihtiyaç duyar ve bu da c9e645a'ya ihtiyaç duyar ... resmi alırsınız. [evet, 4 yıldan fazla olduğunu fark ettim;)]
Bodo Thiesen

2
@brooksbp: Görünüyor, yanılmışım, paket dosyasının sha1 karmalarına göre sıralanması gerekmiyor. Ayrıca, yazarken git, ihtiyaç duyulan nesnelerden önce gerekli nesneleri yazar. Yani, aslında onu paralelleştirebilmelisiniz. Sadece geriye kalan dezavantaj: Daha sonra hangi nesnelere ihtiyaç duyacağınızı bilmediğiniz için, bazılarını tekrar tekrar yeniden oluşturmanız gerekecek. Buraya bakın: kernel.org/pub/software/scm/git/docs/technical/…
Bodo Thiesen

4

Amber, Mercurial veya benzerlerinin kullandığı nesne modelini tarif ediyor gibi görünüyor. Git, bir nesneyi sonraki sürümleri arasında deltaları değil, her seferinde nesnenin tam anlık görüntülerini saklar. Daha sonra bu anlık görüntüleri delta sıkıştırma kullanarak sıkıştırır, geçmişte nerede olursa olsun, kullanılacak iyi deltaları bulmaya çalışır.


5
Aslında, Git gevşek nesneleri saklayabilirken, her zaman böyle depolanmaları gerekmez - gevşek nesneler silinebilir ve paketlenmiş içerikle değiştirilebilir. Amber'ın cevabının sonraki sürümlerle ilgili hiçbir yerde bir şey söylediğini sanmıyorum.
AlBlue
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.