GNU/Linux >> Linux Esercitazione >  >> Linux

Deduplica Git fork su un server

Ora lo stesso file "enorme" risiede in entrambi i fork dello sviluppatore sul server. Non crea automaticamente un collegamento reale

In realtà, con Git 2.20, questo problema potrebbe scomparire, a causa delle isole delta , un nuovo modo di eseguire il calcolo del delta in modo che un oggetto che esiste in un fork non venga trasformato in un delta rispetto a un altro oggetto che non appare nello stesso repository fork .

Vedere commit fe0ac2f, commit 108f530, commit f64ba53 (16 agosto 2018) di Christian Couder (chriscool ).
Aiutato da:Jeff King (peff ) e Duy Nguyen (pclouds ).
Vedere commit 9eb0986, commit 16d75fa, commit 28b8a73, commit c8d521f (16 agosto 2018) di Jeff King (peff ).
Aiutato da:Jeff King (peff ) e Duy Nguyen (pclouds ).

Aggiungi delta-islands.{c,h}

I provider di hosting che consentono agli utenti di eseguire il "fork" dei repository esistenti vogliono che tali fork condividano quanto più spazio possibile su disco.

Le alternative sono una soluzione esistente per conservare tutti gli oggetti di tutti i fork in un repository centrale univoco, ma questo può avere alcuni inconvenienti.
Specialmente quando si impacchetta il repository centrale, verranno creati dei delta tra oggetti di fork diversi.

Ciò può rendere la clonazione o il recupero di un fork molto più lento e molto più impegnativo per la CPU poiché Git potrebbe dover calcolare nuovi delta per molti oggetti per evitare di inviare oggetti da un diverso fork.

Poiché l'inefficienza si verifica principalmente quando un oggetto viene eliminato rispetto a un altro oggetto che non esiste nello stesso fork, suddividiamo gli oggetti in insiemi che compaiono nello stesso fork e definiamo "isole delta".
Quando si trova la base delta, non permettiamo che un oggetto al di fuori della stessa isola venga considerato come sua base.

Quindi "isole delta" è un modo per archiviare oggetti da fork diversi nello stesso repository e file di pacchetto senza avere delta tra oggetti da fork diversi.

Questa patch implementa il meccanismo delle isole delta in "delta-islands.{c,h} ", ma non ne fa ancora uso.

Alcuni nuovi campi sono stati aggiunti in 'struct object_entry ' in "pack-objects.h " però.

Vedi Documentation/git-pack-objects.txt :Isola Delta:

ISOLE DELTA

Quando possibile, pack-objects cerca di riutilizzare i delta su disco esistenti per evitare di doverne cercare di nuovi al volo. Questa è un'ottimizzazione importante per servire i recuperi, perché significa che il server può evitare di gonfiare la maggior parte degli oggetti e inviare semplicemente i byte direttamente dal disco.

Questa ottimizzazione non può funzionare quando un oggetto viene archiviato come delta rispetto a una base che il destinatario non ha (e che non stiamo già inviando). In tal caso il server "rompe" il delta e deve trovarne uno nuovo, che ha un alto costo della CPU. Pertanto è importante per le prestazioni che l'insieme di oggetti nelle relazioni delta su disco corrisponda a ciò che un client recupererebbe.

In un normale repository, questo tende a funzionare automaticamente.
Gli oggetti sono per lo più raggiungibili dai rami e dai tag, ed è quello che i client recuperano. È probabile che qualsiasi delta che troviamo sul server sia tra gli oggetti che il client ha o avrà.

Ma in alcune configurazioni del repository, potresti avere diversi gruppi correlati ma separati di ref tips, con i client che tendono a recuperare quei gruppi in modo indipendente.

Ad esempio, immagina di ospitare diversi "fork" di un repository in un singolo archivio di oggetti condivisi e di consentire ai client di visualizzarli come repository separati tramite GIT_NAMESPACE o repository separati utilizzando il meccanismo alternativo.

Un ingenuo repack potrebbe scoprire che il delta ottimale per un oggetto è rispetto a una base che si trova solo in un altro fork.
Ma quando un client recupera, non avrà l'oggetto di base e dovremo trovare un nuovo delta al volo.

Una situazione simile può verificarsi se hai molti riferimenti al di fuori di refs/heads/ e refs/tags/ che puntano a oggetti correlati (ad esempio, refs/pull o refs/changes utilizzato da alcuni provider di hosting). Per impostazione predefinita, i client recuperano solo head e tag e i delta rispetto agli oggetti trovati solo in quegli altri gruppi non possono essere inviati così come sono.

Le isole delta risolvono questo problema consentendoti di raggruppare i tuoi riferimenti in "isole" distinte .

Pack-objects calcola quali oggetti sono raggiungibili da quali isole e si rifiuta di creare un delta da un oggetto A contro una base che non è presente in tutto il A le isole. Ciò si traduce in pacchetti leggermente più grandi (perché perdiamo alcune opportunità di delta), ma garantisce che il recupero di un'isola non dovrà ricalcolare i delta al volo a causa dell'attraversamento dei confini dell'isola.

Un effetto collaterale però:alcuni comandi erano più prolissi. Git 2.23 (Q3 2019) risolve questo problema.

Vedi commit bdbdf42 (20 giugno 2019) di Jeff King (peff ).

delta-islands :rispetta progress bandiera

Il codice dell'isola delta stampa sempre "Marked %d islands ", anche se il progresso è stato soppresso con --no-progress o inviando stderr a un non-tty.

Passiamo un progress booleano a load_delta_islands() .
Facciamo già la stessa cosa per la barra di avanzamento in resolve_tree_islands() .


Ho deciso di fare questo:

 shared-objects-database.git/
foo.git/
  objects/info/alternate (will have ../../shared-objects-database.git/objects)
bar.git/
  objects/info/alternate (will have ../../shared-objects-database.git/objects)
baz.git/
  objects/info/alternate (will have ../../shared-objects-database.git/objects)

Tutti i fork avranno una voce nel loro file objects/info/alternates che fornisce un percorso relativo al repository del database degli oggetti.

È importante rendere il database degli oggetti un repository, perché possiamo salvare oggetti e riferimenti di utenti diversi che hanno un repository con lo stesso nome.

Passaggi:

  1. git init --bare shared-object-database.git
  2. Eseguo le seguenti righe di codice ogni volta che c'è un push a qualsiasi fork (tramite post-recieve) o eseguendo un cronjob

    for r in list-of-forks
        do
    

    (cd "$r" &&git push ../shared-objects-database.git "refs/:refs/remotes/$r/ " &&echo ../../shared-objects-database.git/objects>objects/info/alternates# da salvare aggiungo gli oggetti "grassi" alle alternative ogni volta)fatto

Quindi nel prossimo "git gc" tutti gli oggetti in fork che già esistono in alternanza verranno cancellati.

git repack -adl è anche un'opzione!

In questo modo risparmiamo spazio in modo che due utenti che spingono gli stessi dati sui rispettivi fork sul server condividano gli oggetti.

Dobbiamo impostare gc.pruneExpire variabile fino a never nel database degli oggetti condivisi. Solo per sicurezza!

Per sfoltire occasionalmente gli oggetti, aggiungi tutti i fork come remoti a shared, fetch e prune! Git farà il resto!

(Finalmente ho trovato una soluzione che funziona per me! (Non testata in produzione! :p Grazie a questo post.)


Linux
  1. Come installare il server HTTP Git con Nginx su Ubuntu 16.04

  2. Come installare HTTP Git Server con Nginx su Ubuntu 20.04

  3. Come installare HTTP Git Server con Nginx su Debian 11

  4. Git Completamento automatico?

  5. Risolvi i problemi di SSH

Come configurare Git Server su Ubuntu 20.04

Come installare Plex Media Server su Ubuntu 16.04 Server/Desktop

Come installare HTTP Git Server su Ubuntu 20.04 LTS

Graylog Monitoring Server su Ubuntu Linux per Monitoring Server/Services

Installazione di Gitea – Un server Git self-hosted su Ubuntu 22.04 LTS

Ridimensiona un server cloud