Close

Git prune

Il comando git prune è un'utilità di pulizia interna che pulisce gli oggetti Git non raggiungibili oppure "orfani". Gli oggetti non raggiungibili sono oggetti inaccessibili da parte dei riferimenti. Qualsiasi commit a cui non è possibile accedere tramite un branch o un tag è considerato non raggiungibile. In genere, git prune non viene eseguito direttamente. È considerato un comando di garbage collection ed è un comando secondario del comando git gc.


Panoramica di git prune


Per comprendere gli effetti di git prune dobbiamo simulare uno scenario in cui un commit diventa non raggiungibile. Quella che segue è una sequenza di esecuzioni della riga di comando volta a simulare questa esperienza.

~ $ cd git-prune-demo/
~/git-prune-demo $ git init .
Initialized empty Git repository in /Users/kev/Dropbox/git-prune-demo/.git/
~/git-prune-demo $ echo "hello git prune" > hello.txt
~/git-prune-demo $ git add hello.txt
~/git-prune-demo $ git commit -am "added hello.txt"

La sequenza di comandi precedente crea un nuovo repository in una directory denominata git-prune-demo. Un commit composto da un nuovo file hello.text viene aggiunto al repository con il contenuto di base di "hello git prune". Modifichiamo quindi hello.txt e creiamo un nuovo commit a partire da tali modifiche.

~/git-prune-demo $ echo "this is second line txt" >> hello.txt
~/git-prune-demo $ cat hello.txt
hello git prune
this is second line txt
~/git-prune-demo $ git commit -am "added another line to hello.txt"
[main 5178bec] added another line to hello.txt
1 file changed, 1 insertion(+)
Database
materiale correlato

Come spostare un repository Git completo

Logo di Bitbucket
Scopri la soluzione

Impara a utilizzare Git con Bitbucket Cloud

Ora abbiamo una cronologia di 2 commit in questo repository dimostrativo. Possiamo eseguire una verifica utilizzando git log:

~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 14:49:59 2018 -0700

        added another line to hello.txt

commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

        added hello.txt

L'output di git log mostra i 2 commit e i messaggi di commit corrispondenti relativi alle modifiche apportate a hello.txt. Il passo successivo è rendere irraggiungibile uno dei commit. Lo faremo utilizzando il comando git reset. Reimpostiamo lo stato del repository al primo commit, ovvero il commit "added hello.txt".

~/git-prune-demo $ git reset --hard 994b122045cf4bf0b97139231b4dd52ea2643c7e
HEAD is now at 994b122 added hello.txt

Se ora utilizziamo git log per esaminare lo stato del repository, possiamo vedere che abbiamo un solo commit.

~/git-prune-demo $ git log
commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

        added hello.txt

Il repository dimostrativo è ora in uno stato che contiene un commit scollegato. Il secondo commit che abbiamo effettuato con il messaggio "added another line to hello.txt" non è più visualizzato nell'output di git log ed è ora scollegato. Può sembrare che il commit sia andato perso o che sia stato eliminato, ma non dimentichiamo che Git fa molta attenzione a non eliminare la cronologia. Possiamo verificare che il commit è ancora disponibile, ma scollegato, utilizzando git checkout per accedervi direttamente:

~/git-prune-demo $ git checkout 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Note: checking out '5178becc2ca965e1728554ce1cb8de2f2c2370b1'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

      git checkout -b <new-branch-name>

HEAD is now at 5178bec... added another line to hello.txt
~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 14:49:59 2018 -0700

      added another line to hello.txt

commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

      added hello.txt

Quando estraiamo il commit scollegato, Git mostra un messaggio dettagliato per informarci che ci troviamo nello stato scollegato. Se esaminiamo il log in questo punto, possiamo vedere che il commit "added another line to hello.txt" è ora di nuovo nell'output del log! Ora che sappiamo che il repository è in un buono stato di simulazione con un commit scollegato, possiamo esercitarci a utilizzare git prune. Prima però, torniamo al branch main usando git checkout

~/git-prune-demo $ git checkout main
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

      5178bec added another line to hello.txt

If you want to keep it by creating a new branch, this may be a good time
to do so with:

     git branch <new-branch-name> 5178bec

Switched to branch 'main'

Quando torniamo al branch principale tramite git checkout, Git ci avvisa che stiamo uscendo da un commit scollegato. È il momento di eliminare questo commit scollegato! Quindi eseguiamo git prune, ma assicurandoci di trasmettere alcune opzioni a questo comando. --dry-run e --verbose mostrano l'output che indica gli elementi impostati per l'eliminazione, ma senza effettivamente eliminarli.

~/git-prune-demo $ git prune --dry-run --verbose

Molto probabilmente questo comando restituirà un output vuoto. L'output vuoto implica che il comando di prune eliminerà effettivamente nulla. Perché succede? Beh, molto probabilmente il commit non è completamente scollegato. Da qualche parte Git mantiene ancora un riferimento ad esso. Questo è un ottimo esempio del motivo per cui git prune non deve essere usato da solo al di fuori di git gc. Ed è anche un buon esempio di come sia difficile perdere completamente i dati con Git.

Molto probabilmente Git archivia un riferimento al nostro commit scollegato nel reflog. Possiamo indagare eseguendo git reflog. git reflog. Dovresti vedere un output che descrive la sequenza delle azioni intraprese per arrivare a questo punto. Per maggiori informazioni su git reflog, visita la pagina git reflog. Oltre a preservare la cronologia nel reflog, in Git sono previste date di scadenza interne in cui verranno eliminati i commit scollegati. Ancora una volta, questi sono tutti dettagli di implementazione gestiti da git gc e non è consigliabile usare git prune in modo indipendente.

Per concludere la nostra dimostrazione di simulazione di git prune, dobbiamo cancellare il reflog

~/git-prune-demo $ git reflog expire --expire=now --expire-unreachable=now --all

Il comando precedente forza la scadenza di tutte le voci nel reflog precedenti al momento attuale. Si tratta di un comando brutale e pericoloso che gli utenti occasionali di Git non dovrebbero mai usare; noi lo stiamo eseguendo per dimostrare l'esecuzione corretta di git prune. Ora che il reflog è stato completamente cancellato, possiamo eseguire git prune.

~/git-prune-demo $ git prune --dry-run --verbose --expire=now
1782293bdfac16b5408420c5cb0c9a22ddbdd985 blob
5178becc2ca965e1728554ce1cb8de2f2c2370b1 commit
a1b3b83440d2aa956ad6482535cbd121510a3280 commit
f91c3433eae245767b9cd5bdb46cd127ed38df26 tree

Questo comando dovrebbe generare una lista di riferimenti agli oggetti Git SHA simile a quella riportata sopra.

Utilizzo


git prune dispone di una breve lista di opzioni descritte nella sezione di panoramica.

-n --dry-run

Non esegue l'eliminazione. Mostra soltanto l'output del comando

-v --verbose

Visualizza l'output di tutti gli oggetti e di tutte le azioni intraprese dal comando di eliminazione

--progress

Visualizza l'output con lo stato di avanzamento dell'eliminazione

--expire <time>

Forza la scadenza degli oggetti successivi

<head>…

Se si specifica un verranno mantenute tutte le opzioni di tale riferimento head

Discussione


Qual è la differenza tra git prune, git fetch --prune e git remote prune?

git remote prune e git fetch --prune hanno la stessa funzione: eliminano i riferimenti ai branch che non esistono sul repository remoto. Sono comandi molto utili quando si lavora in un flusso di lavoro di team in cui i branch remoti vengono eliminati dopo il merge con il branch main. Il secondo comando, git fetch --prune si connette al repository remoto e recupera lo stato remoto più recente prima dell'eliminazione. Si tratta essenzialmente di una combinazione di comandi:

git fetch --all && git remote prune

Il comando generico git prune è completamente diverso. Come discusso nella sezione della panoramica, git prune elimina i commit scollegati localmente.

Come faccio a pulire i branch obsoleti?

git fetch --prune è la migliore utility per la pulizia dei branch obsoleti. Si connette a un repository remoto condiviso e recupera tutti i riferimenti ai branch remoti. Elimina quindi i riferimenti remoti che non sono più in uso nel repository remoto.

Il comando git remote prune origin elimina il branch locale?

No, il comando git remote prune origin elimina solo i riferimenti ai branch remoti che non esistono più. Git archivia i riferimenti locali e remoti. I repository contengono raccolte di riferimenti local/origin e remote/origin. git remote prune origin elimina solo i riferimenti in remote/origin. In questo modo, il lavoro locale rimane protetto in local/origin.

Riepilogo di git prune


Il comando git prune è pensato per essere richiamato come comando secondario di git gc. È altamente improbabile che tu debba mai richiamare git prune durante le attività giornaliere di progettazione software. Sono necessari altri comandi per comprendere gli effetti di git prune. Alcuni comandi usati in questo articolo sono git log, git reflog e git checkout.


Condividi l'articolo
Argomento successivo

Letture consigliate

Aggiungi ai preferiti queste risorse per ricevere informazioni sui tipi di team DevOps e aggiornamenti continui su DevOps in Atlassian.

Le persone collaborano utilizzando una parete piena di strumenti

Blog di Bitbucket

Illustrazione su Devops

Percorso di apprendimento DevOps

Funzione Demo Den per demo con esperti Atlassian

Come Bitbucket Cloud funziona con Atlassian Open DevOps

Iscriviti alla nostra newsletter DevOps

Thank you for signing up