Gestire e archiviare file di grandi dimensioni in Git

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Git consente di mantenere ridotto il footprint del codice sorgente perché le differenze tra le versioni vengono facilmente selezionate e il codice è facilmente compresso. I file di grandi dimensioni che non comprimono bene e che cambiano completamente tra le versioni (ad esempio i file binari) presentano problemi quando vengono archiviati nei repository Git. Le prestazioni veloci di Git derivano dalla possibilità di indirizzare e passare a tutte le versioni di un file dalla risorsa di archiviazione locale.

Se nel repository sono presenti file di grandi dimensioni, che non sono disponibili, ad esempio i file binari, si mantiene una copia completa di tali file nel repository ogni volta che si esegue il commit di una modifica. Se nel repository esistono molte versioni di questi file, aumentano notevolmente il tempo necessario per l'estrazione, il ramo, il recupero e la clonazione del codice.

Quali tipi di file è necessario archiviare in Git?

Eseguire il commit del codice sorgente, non delle dipendenze

Quando il team collabora con editor e strumenti per creare e aggiornare i file, è consigliabile inserire questi file in Git in modo che il team possa sfruttare i vantaggi del flusso di lavoro di Git. Non eseguire il commit di altri tipi di file nel repository, ad esempio DLL, file di libreria e altre dipendenze da cui il team non crea, ma dipende dal codice. Distribuire questi file tramite la gestione dei pacchetti ai sistemi.

La gestione dei pacchetti raggruppa le dipendenze e installa i file nel sistema quando si distribuisce il pacchetto. I pacchetti vengono sottoposti a controllo delle versioni per garantire che il codice testato in un ambiente esegua lo stesso in un altro ambiente, purché gli ambienti abbiano gli stessi pacchetti installati.

Non eseguire il commit degli output

Non eseguire il commit dei file binari, dei log, dell'output di traccia o dei dati di diagnostica dalle compilazioni e dai test. Si tratta di output dal codice, non dal codice sorgente stesso. Condividere i log e le informazioni di traccia con il team tramite strumenti di rilevamento degli elementi di lavoro o tramite la condivisione dei file del team.

Archiviare le origini binarie di piccole dimensioni aggiornate raramente in Git

I file di origine binaria che vengono aggiornati raramente hanno relativamente poche versioni di cui è stato eseguito il commit. Non occupano molto spazio se le dimensioni del file sono ridotte. Le immagini per il Web, le icone e altri asset artistici più piccoli possono rientrare in questa categoria. È preferibile archiviare questi file in Git con il resto dell'origine in modo che il team possa usare un flusso di lavoro coerente.

Importante

Anche i file binari di piccole dimensioni possono causare problemi se vengono aggiornati spesso. Ad esempio, 100 modifiche apportate a un file binario da 100 KB usano la quantità di spazio di archiviazione pari a 10 modifiche a un file binario da 1 MB. A causa della frequenza degli aggiornamenti, il file binario più piccolo rallenta le prestazioni di diramazione più spesso rispetto al file binario di grandi dimensioni.

Non eseguire il commit di asset binari di grandi dimensioni e aggiornati di frequente

Git gestisce una versione principale di un file e quindi archivia solo le differenze rispetto a tale versione, in un processo noto come deltification. La deltification e la compressione dei file consentono a Git di archiviare l'intera cronologia del codice nel repository locale. I file binari di grandi dimensioni cambiano in genere interamente tra le versioni e spesso sono già compressi. Questi file sono difficili da gestire per Git perché le differenze tra le versioni sono di grandi dimensioni.

Git deve archiviare l'intero contenuto di ogni versione del file e ha difficoltà a risparmiare spazio tramite deltification e compressione. L'archiviazione delle versioni complete di questi file determina l'aumento delle dimensioni del repository nel tempo. L'aumento delle dimensioni del repository riduce le prestazioni di diramazione, aumenta i tempi di clonazione ed espande i requisiti di archiviazione.

Strategie per l'uso di file binari di grandi dimensioni

  • Non eseguire il commit degli archivi compressi dei dati. È preferibile decomprimere i file ed eseguire il commit delle origini diffibili. Consentire a Git di comprimere i dati nel repository.
  • Evitare di eseguire il commit del codice compilato e di altre dipendenze binarie. Eseguire il commit dell'origine e compilare le dipendenze oppure usare una soluzione di gestione dei pacchetti per la versione e fornire questi file al sistema.
  • Archiviare la configurazione e altri dati strutturati in formati di testo normale diffibili, ad esempio JSON.

Che cos'è Git LFS?

Quando si dispone di file di origine con grandi differenze tra le versioni e gli aggiornamenti frequenti, è possibile usare Git Large File Archiviazione (LFS) per gestire questi tipi di file. Git LFS è un'estensione di Git che fornisce dati che descrivono i file di grandi dimensioni in un commit nel repository. Archivia il contenuto del file binario in una risorsa di archiviazione remota separata.

Quando si clonano e si cambiano rami nel repository, Git LFS scarica la versione corretta da tale risorsa di archiviazione remota. Gli strumenti di sviluppo locali funzionano in modo trasparente con i file come se fossero stati sottoposti direttamente al commit nel repository.

Vantaggi

Un vantaggio di Git LFS è che il team può usare il flusso di lavoro Git end-to-end familiare indipendentemente dai file creati dal team. LFS gestisce file di grandi dimensioni per impedire che influiscano negativamente sul repository complessivo. Inoltre, a partire dalla versione 2.0, Git LFS supporta il blocco dei file per consentire al team di lavorare su asset di grandi dimensioni e con caratteristiche "undiffable", ad esempio video, suoni e mappe di gioco.

Git LFS è completamente supportato e gratuito in Azure DevOps Services. Per usare LFS con Visual Studio, è necessario Visual Studio 2015 Update 2 o versione successiva. Seguire le istruzioni per installare il client, configurare il rilevamento LFS per i file nel repository locale e quindi eseguire il push delle modifiche in Azure Repos.

Limiti

Git LFS presenta alcuni svantaggi da considerare prima di adottarlo:

  • Ogni client Git usato dal team deve installare il client Git LFS e comprenderne la configurazione di rilevamento.
  • Se il client Git LFS non è installato e configurato correttamente, non verranno visualizzati i file binari di cui è stato eseguito il commit tramite Git LFS quando si clona il repository. Git scaricherà i dati che descrivono il file di grandi dimensioni (ovvero il commit di Git LFS nel repository) e non il file binario. Il commit di file binari di grandi dimensioni senza il client Git LFS installato eseguirà il push del file binario nel repository.
  • Git non può unire le modifiche da due versioni diverse di un file binario, anche se entrambe le versioni hanno un padre comune. Se due persone lavorano contemporaneamente sullo stesso file, dovranno collaborare per riconciliare le modifiche per evitare di sovrascrivere il lavoro dell'altro. Git LFS fornisce il blocco dei file per facilitare l'operazione. Gli utenti devono comunque prestare attenzione a eseguire sempre il pull della copia più recente di un asset binario prima di iniziare il lavoro.
  • Azure Repos attualmente non supporta l'uso di Secure Shell (SSH) nei repository con i file rilevati di Git LFS.
  • Se un utente trascina un file binario tramite l'interfaccia Web in un repository configurato per Git LFS, viene eseguito il commit del file binario nel repository e non nei puntatori di cui viene eseguito il commit tramite il client Git LFS.
  • Anche se non esiste una restrizione rigorosa sulle dimensioni dei file, lo spazio disponibile del server e il carico di lavoro corrente potrebbero limitare le prestazioni e le funzionalità.
  • Il limite di tempo per un caricamento di file è di un'ora.

File format

Il file scritto nel repository per un file rilevato Git LFS include alcune righe con una coppia chiave/valore in ogni riga:

version https://git-lfs.github.com/spec/v1
oid a747cfbbef63fc0a3f5ffca332ae486ee7bf77c1d1b9b2de02e261ef97d085fe
size 4923023

Nota

L'URL di GitHub incluso per il valore della versione definisce solo il tipo di file puntatore LFS. Non è un collegamento al file binario.

Problemi noti

Se si usa una versione di LFS precedente alla 2.4.0 con Azure DevOps Server, è necessario un passaggio di configurazione aggiuntivo per l'autenticazione tramite NTLM anziché Kerberos. Questo passaggio non è più necessario a partire da LFS 2.4.0 ed è consigliabile eseguire l'aggiornamento.