Co właściwie robi git, gdy mówi, że to „rozwiązywanie delt”?

187

Podczas pierwszego klonowania repozytorium, git najpierw otrzymuje obiekty (co jest dość oczywiste), a następnie spędza mniej więcej tyle samo czasu na „rozwiązywaniu delt”. Co tak naprawdę dzieje się w tej fazie klonowania?

Nik Reiman
źródło
Powiązane: stackoverflow.com/questions/9478023/...
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
Zobacz także Git 2.20 (IV kwartał 2018 r.) I więcej wysp delta: stackoverflow.com/a/52458712/6309
VonC

Odpowiedzi:

54

Git używa kodowania delta do przechowywania niektórych obiektów w plikach pakietów. Jednak nie chce mieć, aby odtworzyć każdą zmianę kiedykolwiek na danym pliku w celu uzyskania aktualnej wersji, więc Git posiada również okolicznościowe migawek zawartości plików zapisanych jako dobrze. „Rozstrzyganie delt” to krok polegający na upewnieniu się, że wszystko pozostaje spójne.

Oto rozdział z sekcji „Git Internals” książki Pro Git, która jest dostępna online, która mówi o tym.

Bursztyn
źródło
80
Ta odpowiedź jest niepoprawna. Zdaje się opisywać, jak działa Mercurial, a nie Git. Pojawia się w wynikach wyszukiwania tego problemu przez Google, więc czuję potrzebę odpowiedzi. Git nie przechowuje różnic między zatwierdzeniami jako delty; Git to magazyn „całego obiektu”. Jako taki, Git nie potrzebuje „migawek”, aby pokazać dany plik, ponieważ historii plików nie trzeba odtwarzać z delt. Tak działa Mercurial.
Nexus mówi
12
Jedyne miejsce, w którym włącza się kodowanie delta, znajduje się w pliku pakietu, który jest przeznaczony wyłącznie do kompresji i przesyłania - nie zmienia to sposobu, w jaki Git „widzi” świat. ( kernel.org/pub/software/scm/git/docs/v1.6.2.3/technical/... ) Dokładna odpowiedź znajduje się poniżej w odpowiedzi araqnid.
Nexus mówi
4
Wszystkie „migawki” oznaczają w tym kontekście pełną kopię stanu pliku, a nie wersję w formacie delta. Jak już wspomniano, Git robi use delta-kodowanie w packfiles. Nikt nie powiedział, że „zmienia to, jak Git postrzega świat”; przestańcie projektować własne założenia.
Amber
2
Twoja odpowiedź jest wciąż niedokładna. „Git ma również sporadyczne migawki zawartości pliku.” -- to nie jest poprawne. „Rozwiązanie problemów z deltami to krok polegający na upewnieniu się, że wszystko pozostaje spójne”. - to również nie jest poprawne, poniższa odpowiedź araqnid jest poprawna.
Nexus mówi
1
Jak opisano w powyższym rozdziale, Git zawsze przechowuje pełną zawartość najnowszej wersji pliku. Poprzednie wersje są zapisywane jako pliki w formacie delta, gdy są plikami „luźnymi”. Okresowo (dzwoniąc git gclub kiedy Git uzna to za konieczne) Git skompresuje wszystkie „luźne” pliki do pliku pakietu, aby zaoszczędzić miejsce, i utworzony zostanie plik indeksu w tym pliku pakietu. Więc zlib będzie kompresował przy użyciu własnego algorytmu delta, ale Git używa kodowania delta do przechowywania wcześniejszych wersji. Ponieważ najczęstszym i najczęstszym dostępem jest najnowsza wersja, która jest przechowywana jako migawka.
BrionS
118

Etapy git cloneto:

  1. Odbierz plik „paczki” wszystkich obiektów w bazie danych repo
  2. Utwórz plik indeksu dla otrzymanej paczki
  3. Sprawdź wersję główną (oczywiście repozytorium non-bare)

„Rozwiązywanie delt” to komunikat pokazany dla drugiego etapu, indeksujący plik paczki („git index-pack”).

Pliki paczek nie zawierają rzeczywistych identyfikatorów obiektów, a jedynie treść obiektu. Aby ustalić, czym są identyfikatory obiektów, git musi wykonać dekompresję + SHA1 każdego obiektu w pakiecie, aby wygenerować identyfikator obiektu, który jest następnie zapisywany w pliku indeksu.

Obiekt w pliku paczki może być przechowywany jako delta, tj. Sekwencja zmian, które należy wprowadzić w innym obiekcie. W takim przypadku git musi pobrać obiekt podstawowy, zastosować polecenia i SHA1 wynik. Sam obiekt podstawowy może wymagać wyodrębnienia przez zastosowanie sekwencji poleceń delta. (Mimo że w przypadku klonu obiekt bazowy został już napotkany, istnieje ograniczenie liczby przechowywanych obiektów w pamięci podręcznej).

Podsumowując, etap „rozwiązywania delt” obejmuje dekompresję i sumowanie kontrolne całej bazy danych repo, co nie jest zaskakujące dość długo. Przypuszczalnie dekompresja i obliczanie SHA1 zajmuje więcej czasu niż stosowanie poleceń delta.

W przypadku kolejnego pobierania, odebrany plik paczki może zawierać odniesienia (jako podstawy obiektów delta) do innych obiektów, które powinien mieć już otrzymujący git. W takim przypadku git odbierający faktycznie przepisuje odebrany plik paczki, aby zawierał takie odwołania do obiektów, tak że każdy przechowywany plik paczki jest samowystarczalny. To może być początek wiadomości „rozwiązywanie delt”.

araqnid
źródło
7
Czy można to zrównoleglić?
brooksbp 17.04.13
Czy ta kompresja delta to więcej niż przechowywanie wielu obiektów w jednym strumieniu danych zlib?
fuz
1
@FUZxxl tak, używa algorytmu takiego jak diff lub xdelta do porównania dwóch obiektów blob i utworzenia skryptu edycji
araqnid
@brooksbp: Tylko z ograniczeniami. Ponieważ obiekt o identyfikatorze 103fa49 może wymagać dekodowania df85b51, ale gdy otrzymasz 103fa49, df85b51 jeszcze go nie ma (pliki paczek są ściśle uporządkowane według skrótów sha1). Tak więc dla wszystkiego, co odnosi się tylko do rzeczy, które już tam są, rzeczy są łatwe, ale na wszystko inne musisz poczekać, aż zostaną odebrane. I ta kompresja delta może być zagnieżdżona, więc 103fa49 może potrzebować 4e9ba42, które z kolei potrzebują 29ad945, które z kolei potrzebują c9e645a ... otrzymujesz obraz. [tak, zauważyłem, że minęły> 4 lata;)]
Bodo Thiesen
2
@brooksbp: Okazuje się, że się myliłem, plik paczki NIE musi być sortowany według skrótów sha1. Ponadto, podczas pisania, git zapisuje potrzebne obiekty, zanim obiekty będą ich potrzebować. Tak więc właściwie powinieneś być w stanie to zrównoleglić. Pozostaje tylko wada: ponieważ nie wiesz, które obiekty będą potrzebne później, będziesz musiał wielokrotnie je odtwarzać. Zobacz tutaj: kernel.org/pub/software/scm/git/docs/technical/…
Bodo Thiesen
4

Bursztyn wydaje się opisywać model obiektowy, który wykorzystuje Mercurial lub podobny. Git nie przechowuje delt między kolejnymi wersjami obiektu, ale za każdym razem pełne migawki obiektu. Następnie kompresuje te migawki za pomocą kompresji delta, próbując znaleźć dobre delty do użycia, niezależnie od tego, gdzie w historii one istnieją.

Johan
źródło
5
W rzeczywistości, chociaż Git może przechowywać luźne obiekty, nie zawsze są one przechowywane jako takie - ponieważ luźne obiekty można usunąć i zastąpić spakowaną zawartością. Nie sądzę, aby odpowiedź Amber mówiła cokolwiek o kolejnych wersjach.
AlBlue,