Padroneggiare la Garbage Collection di Git per Prestazioni Ottimali

Scopri quando eseguire git gc, cosa pulisce e come evitare una pulizia aggressiva rischiosa su repository attivi.

Padroneggiare la Garbage Collection di Git per Prestazioni Ottimali

La garbage collection di Git impedisce al tuo repository di accumulare oggetti sparsi, commit irraggiungibili obsoleti e file pack inefficienti per sempre. Se il tuo repo è lento, occupa troppo spazio su disco o ha subito molti rebase e pulizie di rami, git gc è uno dei primi strumenti di manutenzione da comprendere.

Di solito non è necessario eseguirlo ogni giorno. Git esegue la manutenzione automatica durante i comandi normali quando vengono raggiunte determinate soglie. Tuttavia, sapere cosa fa ti aiuta a evitare due errori comuni: ignorare un repository gonfio per mesi o eseguire una pulizia aggressiva su un repo condiviso senza capirne l'impatto.

Cosa Fa la Garbage Collection di Git

Git memorizza i dati come oggetti: commit, alberi, blob e tag. I nuovi oggetti possono iniziare come file sparsi nella directory .git/objects/. Col tempo, Git può impacchettare molti oggetti insieme in file pack compatti. Gli oggetti impacchettati utilizzano il disco in modo più efficiente e di solito sono più veloci da scansionare per Git.

git gc esegue diverse attività di manutenzione, tra cui:

  • Impacchettare oggetti sparsi in file pack.
  • Consolidare file pack esistenti quando utile.
  • Rimuovere oggetti irraggiungibili abbastanza vecchi da essere potati.
  • Pulire file temporanei lasciati da operazioni interrotte.
  • Aggiornare dati ausiliari come i file commit-graph nelle configurazioni Git moderne quando configurato.

Irraggiungibile non significa sempre sicuro da eliminare immediatamente. Un commit può diventare irraggiungibile dopo un rebase, un amend, un reset o un ramo cancellato. Git di solito mantiene gli oggetti recentemente irraggiungibili per un periodo di grazia in modo da avere tempo per recuperarli con git reflog.

Controlla la Dimensione del Repository Prima di Pulire

Inizia misurando il repository invece di indovinare:

git count-objects -vH

I campi utili includono count, size, in-pack, packs e size-pack. Un numero elevato di oggetti sparsi può rallentare le operazioni quotidiane di Git. Un size-pack grande può semplicemente significare che il repository ha molta storia reale, file binari di grandi dimensioni o risorse di terze parti.

Per ispezionare direttamente l'uso del disco, esegui:

du -sh .git

Se .git è enorme perché qualcuno ha committato artefatti di build o archivi di grandi dimensioni, la sola garbage collection potrebbe non risolvere il problema reale. Potrebbe essere necessario rimuovere i file grandi dai commit futuri, spostarli su Git LFS o riscrivere la storia con uno strumento come git filter-repo dopo aver coordinato con il team.

Esegui la Garbage Collection Normale

Per una pulizia di routine, usa:

git gc

Questa è l'impostazione predefinita sicura. Lascia che Git decida quale lavoro di manutenzione vale la pena fare e rispetta le regole di potatura normali.

Puoi chiedere a Git di eseguire la manutenzione automatica solo se le soglie lo richiedono:

git gc --auto

La maggior parte degli utenti non ha bisogno di chiamare --auto manualmente perché Git lo fa già in background. È comunque utile negli script in cui si desidera un passaggio di pulizia a basso costo senza forzare un reimpacchettamento completo ogni volta.

Se vuoi rimuovere vecchi oggetti irraggiungibili utilizzando il periodo di grazia standard, esegui:

git gc --prune=now

Usa --prune=now con cautela. Può rimuovere punti di recupero che git reflog potrebbe altrimenti aiutarti a trovare. Evitalo subito dopo un rebase complicato, una cancellazione di ramo o un reset, a meno che tu non sia certo di non aver bisogno dei vecchi oggetti.

Fai Attenzione con --aggressive

git gc --aggressive dice a Git di spendere più tempo CPU cercando di ottimizzare l'impacchettamento degli oggetti:

git gc --aggressive

Non è un pulsante magico per la velocità. Su molti repository, il lavoro extra dà pochi benefici rispetto al normale git gc e può richiedere molto tempo su storie grandi. Usalo solo quando hai misurato un problema reale di dimensione del repository o di prestazioni e puoi permetterti una finestra di manutenzione.

Per il lavoro quotidiano, preferisci il semplice git gc. Se il tuo repository necessita regolarmente di una pulizia aggressiva, il problema più profondo sono spesso file grandi, artefatti generati o un flusso di lavoro che crea molta storia irraggiungibile.

Usa la Manutenzione Moderna di Git per la Cura Continua

Le versioni recenti di Git includono git maintenance, che può pianificare attività in background come il prefetching, gli aggiornamenti del commit-graph e il reimpacchettamento incrementale a seconda della piattaforma e della configurazione.

Per eseguire la manutenzione una volta:

git maintenance run

Per abilitare la manutenzione pianificata per il tuo account utente:

git maintenance start

Controlla la tua versione di Git e la documentazione locale prima di affidarti alla manutenzione pianificata nell'automazione, perché l'integrazione esatta del pianificatore differisce in base al sistema operativo e alla build di Git.

Flusso di Lavoro Pratico per la Pulizia

Un flusso di pulizia sicuro per un repository locale è il seguente:

git status
git count-objects -vH
git gc
git count-objects -vH

Assicurati che il tuo albero di lavoro sia pulito prima della manutenzione. Git può eseguire la garbage collection con modifiche locali presenti, ma un albero pulito rimuove i dubbi se devi risolvere problemi in seguito.

Per un repository bare condiviso su un server, pianifica la manutenzione durante un periodo di inattività. Evita di eseguire reimpacchettamenti pesanti durante il picco di attività CI, perché le operazioni di clone, fetch e push potrebbero competere per disco e CPU.

Quando la Garbage Collection Non Aiuta

La garbage collection non può risolvere tutti i repository Git lenti. Non rimuoverà i file che sono ancora raggiungibili nella storia. Non renderà piccolo un monorepo se la storia attiva contiene genuinamente anni di risorse di grandi dimensioni. Non riparerà un repository corrotto da sola.

Se le prestazioni sono ancora scarse dopo una pulizia normale, cerca queste cause:

  • File binari di grandi dimensioni committati direttamente in Git.
  • Troppi file generati tracciati nel repository.
  • Antivirus o indicizzazione del filesystem che scansiona .git ad ogni operazione.
  • Storage di rete lento che ospita l'albero di lavoro.
  • Alberi di lavoro molto grandi in cui un checkout sparso potrebbe aiutare.

Usa git gc come manutenzione, non come sostituto dell'igiene del repository. Esegui una pulizia normale quando il conteggio degli oggetti cresce, evita la pulizia aggressiva a meno che tu non abbia misurato una necessità e tratta gli artefatti tracciati di grandi dimensioni come un problema del flusso di lavoro da risolvere alla fonte.