Corso
Git adotta un approccio protettivo all'eliminazione dei dati per evitare la perdita accidentale di commit o dati importanti.
Tuttavia, questo può far sì che dati obsoleti, come i riferimenti a branch eliminati, restino visibili. Col tempo, i repository Git possono accumulare oggetti non referenziati, che consumano spazio su disco inutilmente e possono creare confusione.
Il comando git prune è un'utility di manutenzione in Git, pensata principalmente per ripulire gli oggetti irraggiungibili nel repository.
Un oggetto irraggiungibile è un oggetto a cui non si può accedere da alcun branch, tag, branch di tracking remoto o altro riferimento. Questi oggetti possono occupare spazio nel repository, riempiendolo nel tempo di dati non necessari.
Sebbene git prune sia uno strumento potente per mantenere i repository snelli, la maggior parte degli utenti potrebbe non averne bisogno direttamente grazie alla garbage collection automatica di Git (git gc). Capirne ruolo e funzionamento può comunque essere utile per utenti avanzati o in scenari specifici in cui si preferisce o si richiede la manutenzione manuale del repository.
Che cos'è git prune?
Il comando git prune viene usato per rimuovere gli oggetti che non sono più necessari nel repository locale. Questi oggetti possono essere commit, tree (istantanee di directory), blob (file) e tag che non sono più accessibili da alcun branch o tag nel repository.
In poche parole, git prune aiuta a ripulire file e dati non necessari nel repository, risparmiando spazio e riducendo il disordine.
Come possono diventare irraggiungibili gli oggetti?
Gli oggetti possono diventare irraggiungibili in vari modi—per esempio eliminando branch o riscrivendo commit. Quando si eliminano branch, i commit unici di quei branch che non fanno parte di nessun altro branch o tag diventano irraggiungibili.
La riscrittura dei commit, usando comandi come git rebase, genera nuovi commit e scarta i vecchi, rendendo irraggiungibili anche questi ultimi.
Periodo di grazia e reflog
Git mantiene un registro degli aggiornamenti delle punte dei branch e di altri riferimenti chiamato reflog (reference log). Possiamo visualizzarlo con il comando git reflog.
Anche se un oggetto è irraggiungibile, se è ancora nel reflog non verrà eliminato da git prune.
Per impostazione predefinita, il reflog ha una scadenza di 90 giorni, offrendo un periodo di grazia durante il quale gli oggetti irraggiungibili vengono conservati temporaneamente e non vengono subito rimossi.
Quando usare git prune
In generale, non serve usare direttamente git prune. Git ha un meccanismo di garbage collection che viene eseguito automaticamente dopo alcuni comandi per ripulire i file non necessari e ottimizzare l'efficienza del repository locale comprimendo alcuni file.
Tuttavia, potremmo voler ripulire manualmente il repository, ad esempio:
- Dopo aver eseguito un'operazione che sappiamo creerà oggetti irraggiungibili, come l'eliminazione di un branch.
- Se vogliamo liberare subito spazio su disco.
- Per mantenere il repository sempre in ordine e pulito.
Garbage collection con git gc
Invece del pruning diretto, di solito si consiglia di affidarsi al meccanismo di garbage collection, che non solo esegue un git prune ma ottimizza anche lo spazio comprimendo gli oggetti.
Come accennato sopra, la garbage collection viene eseguita automaticamente dopo alcuni comandi. Possiamo avviarla manualmente con il comando:
git gc
Come usare git prune
Poiché git prune elimina dei dati, è consigliabile eseguirlo prima con l'opzione --dry-run.
git prune --dry-run
Questa opzione elenca gli oggetti che verrebbero rimossi senza eliminarli davvero. L'output potrebbe apparire così:
0d7dff8258654c03a058987b3e63c86feca9200d commit
ea1380f52f0bfa0142e46767adfd56593681091a blob
fa91af78a1ab453c1d7632192b3ca8bf217ec711 commit
L'output indica che ci sono due commit e un blob irraggiungibili che verrebbero eliminati. Dopo aver verificato che non ci siano dati importanti in elenco, possiamo procedere con la pulizia:
git prune
In alcune situazioni, vogliamo ripulire il repository subito dopo aver eseguito un'azione che sappiamo porterà a oggetti irraggiungibili, come l'eliminazione di un branch. Potremmo eseguire git prune --dry-run, ma l'output risulta vuoto. Il motivo è che i commit eliminati sono ancora referenziati nel reflog.
Se non vogliamo aspettare che scadano dal reflog, possiamo farli scadere manualmente con il comando:
git reflog expire --expire-unreachable=now --all
Vediamo nel dettaglio le opzioni usate:
- L'opzione
--expire-unreachable=nowimposta la scadenza di tutti gli oggetti irraggiungibili a ora, facendoli di fatto scadere immediatamente. - L'opzione
--allapplica l'operazione a tutte le voci del reflog nel repository. Senza questa opzione, dovremmo specificare un ref particolare (come un branch o un tag) su cui operare.
git prune: utilizzo avanzato
Vediamo alcune tecniche avanzate, come specificare un tempo di scadenza o rimuovere gli oggetti già impacchettati.
Specificare un tempo di scadenza
Potremmo voler rimuovere solo gli oggetti irraggiungibili più vecchi, ad esempio eliminando solo quelli con almeno due settimane.
L'opzione --expire <time> ci permette di specificare una soglia temporale. Git rimuoverà gli oggetti che sono irraggiungibili da più del tempo indicato. Il parametro <time> accetta formati diversi come "2 weeks ago", "3 days", "yesterday", ecc., offrendo flessibilità nel definire il periodo di scadenza.
Esempio di comando:
git prune --expire=2.weeks.ago
Rimozione degli oggetti impacchettati
Git archivia gli oggetti in due modi principali: come file singoli (oggetti loose) e in file impacchettati. Il packing è un meccanismo per risparmiare spazio e migliorare le prestazioni archiviando più oggetti in un unico file e rimuovendo le ridondanze.
A volte, un oggetto può esistere sia in forma loose che impacchettata. Anche se questa ridondanza non è dannosa (oltre a occupare un po' di spazio in più), potremmo voler eliminare gli oggetti loose che sono già impacchettati per recuperare spazio.
Il comando git prune-packed rimuove gli oggetti loose se sono già inclusi in un pack. A differenza di git prune, git prune-packed non accetta opzioni come --expire <time>. Si limita a ripulire gli oggetti loose che sono già stati impacchettati.
Conclusione
Usando un repository, alcuni oggetti diventeranno irraggiungibili, causando un uso di spazio su disco non necessario. Git gestisce questo aspetto con un sistema di garbage collection che elimina gli oggetti irraggiungibili dopo un certo periodo di inattività.
Il meccanismo di garbage collection viene eseguito automaticamente da Git dopo alcuni comandi. Possiamo però avviarlo anche manualmente con il comando git gc. Il processo di garbage collection non solo rimuove gli oggetti irraggiungibili usando git prune, ma ottimizza anche lo spazio su disco comprimendo alcuni oggetti.
Gli utenti avanzati di Git possono voler mantenere manualmente un repository pulito. Il comando git prune consente l'eliminazione manuale degli oggetti irraggiungibili. È bene eseguire sempre git prune --dry-run prima di git prune per avere una panoramica degli oggetti che verranno eliminati durante il pruning.


