Cosa sta realmente facendo git quando dice che sta "risolvendo i delta"?


187

Durante il primo clone di un repository, git prima riceve gli oggetti (il che è abbastanza ovvio), quindi passa circa la stessa quantità di tempo a "risolvere i delta". Cosa sta realmente accadendo durante questa fase del clone?



1
Si veda anche, per Git 2.20 (Q4 2018) e più isole delta: stackoverflow.com/a/52458712/6309
VonC

Risposte:


54

Git utilizza la codifica delta per archiviare alcuni degli oggetti in pacchetti. Tuttavia, non si vuole avere a riprodurre ogni singola modifica mai su un dato file al fine di ottenere la versione attuale, in modo da Git ha anche istantanee occasionali del contenuto di file memorizzati pure. "Risolvere i delta" è il passo che consiste nel garantire che tutto ciò rimanga coerente.

Ecco un capitolo della sezione "Git Internals" del libro Pro Git, disponibile online, che ne parla.


80
Questa risposta non è corretta Sembra descrivere come funziona Mercurial, non Git. Sta arrivando nelle ricerche di Google per questo problema, quindi sento il bisogno di rispondere. Git non memorizza le differenze tra commit come delta; Git è un negozio "intero oggetto". Pertanto, Git non ha bisogno di "istantanee" per mostrare un dato file perché non è necessario ricostruire la cronologia dei file dai delta. Ecco come funziona Mercurial.
Nexus dice il

12
L'unico posto in cui entra in gioco la codifica delta è nel file pack che è strettamente per la compressione e il trasferimento - non altera il modo in cui Git "vede" il mondo. ( kernel.org/pub/software/scm/git/docs/v1.6.2.3/technical/… ) Consultare la risposta di araqnid di seguito per una risposta accurata.
Nexus dice il

4
Tutte le "istantanee" significano che in questo contesto è una copia completa di uno stato del file, piuttosto che una versione con codifica delta. Come lei ha ricordato, Git fa uso delta-codifica in packfiles. Nessuno ha detto che "altera il modo in cui Git vede il mondo"; per favore, smetti di proiettare i tuoi presupposti.
Ambra

2
La tua risposta è ancora imprecisa "Git ha anche delle istantanee occasionali del contenuto del file memorizzato." - non è corretto. "'Risolvere i delta' è il passo che consiste nel garantire che tutto ciò rimanga coerente." - anche questo non è corretto, la risposta di araqnid sotto è corretta.
Nexus dice il

1
Come descritto nel capitolo sopra citato, Git memorizza sempre il contenuto completo del file dell'ultima versione. Le versioni precedenti vengono archiviate come file delta quando sono file "allentati". Periodicamente (chiamando git gco ogni volta che Git lo ritiene necessario) Git comprimerà tutti i file "sciolti" in un file pack per risparmiare spazio e verrà creato un file indice in quel file pack. Quindi zlib comprime con il suo algoritmo delta ma Git usa la codifica delta per memorizzare le versioni precedenti. Poiché l'accesso più comune e frequente è l'ultima versione, che viene archiviata come un'istantanea.
BrionS,

118

Le fasi di git clonesono:

  1. Ricevi un file "pack" di tutti gli oggetti nel database repo
  2. Creare un file indice per il pacchetto ricevuto
  3. Dai un'occhiata alla revisione principale (per un repo non nudo, ovviamente)

"Risoluzione dei delta" è il messaggio mostrato per la seconda fase, indicizzando il file del pacchetto ("git index-pack").

I file pack non contengono gli ID oggetto effettivi, ma solo il contenuto dell'oggetto. Quindi, per determinare quali sono gli ID oggetto, git deve fare una decompressione + SHA1 di ciascun oggetto nel pacchetto per produrre l'ID oggetto, che viene quindi scritto nel file indice.

Un oggetto in un file pack può essere archiviato come un delta, ovvero una sequenza di modifiche da apportare a qualche altro oggetto. In questo caso, git deve recuperare l'oggetto base, applicare i comandi e SHA1 il risultato. L'oggetto base stesso potrebbe dover essere derivato applicando una sequenza di comandi delta. (Anche se nel caso di un clone, l'oggetto base sarà già stato rilevato, esiste un limite al numero di oggetti fabbricati che sono memorizzati nella cache).

In sintesi, la fase "risoluzione dei delta" prevede la decompressione e il checksum dell'intero database di repository, che non sorprendentemente richiede molto tempo. Presumibilmente decomprimere e calcolare gli SHA1 richiede in realtà più tempo rispetto all'applicazione dei comandi delta.

Nel caso di un successivo recupero, il file del pacchetto ricevuto può contenere riferimenti (come basi di oggetti delta) ad altri oggetti che ci si aspetta già dal git di ricezione. In questo caso, git di ricezione riscrive effettivamente il file del pacchetto ricevuto per includere tali oggetti referenziati, in modo che qualsiasi file del pacchetto memorizzato sia autosufficiente. Questo potrebbe essere il punto di origine del messaggio "risoluzione dei delta".


7
Questo può essere parallelizzato?
brooksbp,

Questa compressione delta è più della memorizzazione di più oggetti in un flusso di dati zlib?
fuz

1
@FUZxxl sì, sta usando un algoritmo come diff o xdelta per confrontare due BLOB e produrre uno script di modifica
araqnid

@brooksbp: solo con limitazioni. Poiché l'oggetto con ID 103fa49 potrebbe richiedere la decodifica di df85b51, ma quando si riceve 103fa49, df85b51 non è ancora presente (i file del pacchetto sono rigorosamente ordinati da hash sha1). Quindi, per tutto ciò che fa riferimento solo a cose che sono già lì, le cose sono facili, ma per tutto il resto, dovrai aspettare fino a quando non viene ricevuto. E questa compressione delta può essere nidificata, quindi 103fa49 potrebbe aver bisogno di 4e9ba42 che a sua volta ha bisogno di 29ad945 che a sua volta ha bisogno di c9e645a ... ottieni l'immagine. [sì, ho notato che sono passati> 4 anni;)]
Bodo Thiesen il

2
@brooksbp: A quanto pare, ho sbagliato, il file del pacchetto NON deve essere ordinato in base agli hash sha1. Inoltre, durante la scrittura, git scrive gli oggetti necessari prima che siano necessari agli oggetti. Quindi, in realtà dovresti essere in grado di parallelizzarlo. L'unico svantaggio che rimane: poiché non sai quali oggetti ti serviranno in seguito, dovrai ricrearne ancora e ancora. Vedi qui: kernel.org/pub/software/scm/git/docs/technical/…
Bodo Thiesen

4

L'ambra sembra descrivere il modello a oggetti che Mercurial o simili usano. Git non memorizza i delta tra le versioni successive di un oggetto, ma piuttosto istantanee complete dell'oggetto, ogni volta. Comprime quindi queste istantanee usando la compressione delta, cercando di trovare buoni delta da usare, indipendentemente da dove nella storia esistano.


5
In realtà, mentre Git è in grado di archiviare oggetti sfusi, non sono necessariamente sempre archiviati come tali, poiché gli oggetti sfusi possono essere eliminati e sostituiti con contenuto impacchettato. Non credo che la risposta di Amber abbia detto nulla sulle versioni successive.
AlBlue,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.