Come potare i rami di localizzazione locali che non esistono più sul telecomando

Con git remote prune origin ansible rimuovere i rami locali che non si trovano più sul telecomando.

Ma voglio anche rimuovere i rami locali che sono stati creati da quelle filiali remote (un controllo se sono immersi sarebbe bello).

Come posso fare questo?

Dopo la potatura, puoi ottenere l’elenco delle filiali remote con git branch -r . L’elenco delle filiali con il loro ramo di monitoraggio remoto può essere recuperato con git branch -vv . Quindi, utilizzando questi due elenchi, è ansible trovare i rami di monitoraggio remoto che non si trovano nell’elenco dei telecomandi.

Questa linea dovrebbe fare il trucco (richiede bash o zsh , non funzionerà con la shell Bourne standard):

git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 < (git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d

Questa stringa ottiene l'elenco dei rami remoti e lo passa in egrep attraverso l'input standard. E filtra i rami che hanno un ramo di rintracciamento remoto (usando git branch -vv e il filtro per quelli che hanno origin ), quindi ottenendo la prima colonna di quell'output che sarà il nome del ramo. Infine, passando tutti i nomi dei rami nel comando delete branch.

Poiché utilizza l'opzione -d , non eliminerà i rami che non sono stati uniti nel ramo in cui ci si trova quando si esegue questo comando.

Ricorda inoltre che devi eseguire git fetch --prune prima , altrimenti git branch -r vedrà comunque i rami remoti.

Se si desidera eliminare tutti i rami locali già uniti in master, è ansible utilizzare il seguente comando:

 git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d 

Maggiori informazioni

Tra le informazioni presentate da git help fetch , c’è questo piccolo object:

  -p, --prune After fetching, remove any remote-tracking branches which no longer exist on the remote. 

Quindi, forse, git fetch -p è quello che stai cercando?

EDIT: Ok, per chi ancora discute questa risposta 3 anni dopo il fatto, ecco un po ‘più di informazioni sul perché ho presentato questa risposta …

Innanzitutto, l’OP dice di voler “rimuovere anche i rami locali creati da quelle diramazioni remote [che non sono più sul telecomando]”. Questo non è inequivocabilmente ansible in git . Ecco un esempio.

Diciamo che ho un repository su un server centrale, e ha due rami, chiamati A e B Se clone il repository sul mio sistema locale, il mio clone avrà i riferimenti locali (non ancora rami effettivi) chiamati origin/A e origin/B Ora diciamo che faccio quanto segue:

 git checkout -b A origin/A git checkout -b Z origin/B git checkout -b C  

I fatti pertinenti qui sono che per qualche ragione ho scelto di creare un ramo sul mio repository locale che ha un nome diverso da quello di origine, e ho anche un ramo locale che non esiste (ancora) sul repository di origine.

Ora diciamo che rimuovo entrambi i rami A e B sul repository remoto e aggiorno il mio repository locale ( git fetch di qualche modulo), il che fa sì che i miei refs locali origin/A e origin/B scompaiano. Ora, il mio repository locale ha ancora tre rami, A , Z e C Nessuno di questi ha un ramo corrispondente sul repository remoto. Due di loro erano “creati da … rami remoti”, ma anche se so che c’era un ramo chiamato B sull’origine, non ho modo di sapere che Z stato creato da B , perché è stato rinominato in il processo, probabilmente per una buona ragione. Quindi, in realtà, senza un processo esterno che registra i metadati di origine dei rami o un umano che conosce la cronologia, è imansible stabilire quale dei tre rami, se presente, l’OP sta cercando di rimuovere. Senza alcune informazioni esterne che git non gestisce automaticamente per te, git fetch -p è il più vicino ansible e qualsiasi metodo automatico per tentare letteralmente ciò che l’OP ha richiesto rischia di eliminare troppi rami o di perdere alcuni che l’OP altrimenti vorrebbe cancellato.

Esistono anche altri scenari, ad esempio se creo tre rami distinti origin/A per testare tre diversi approcci a qualcosa, e quindi l’ origin/A scompare. Ora ho tre rami, che ovviamente non possono tutti corrispondere al nome, ma sono stati creati origin/A , e quindi un’interpretazione letterale della domanda OPs richiederebbe la rimozione di tutti e tre. Tuttavia, potrebbe non essere desiderabile, se potessi anche trovare un modo affidabile per abbinarli …

Questo eliminerà i rami locali per i quali i rami di tracciamento remoto sono stati eliminati. (Assicurati di essere nel ramo master !)

 git checkout master git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -d 

Dettagli:

  • git branch -vv visualizza “gone” per i rami locali che il telecomando è stato potato.

     mybranch abc1234 [origin/mybranch: gone] commit comments 
  • -d controllerà se è stato unito ( -D lo eliminerà a prescindere)

     error: The branch 'mybranch' is not fully merged. 

È ansible configurare Git per rimuovere automaticamente i riferimenti ai rami remoti eliminati durante il recupero:

 git config --global fetch.prune true 

Quando si chiama git fetch o git pull seguito, i riferimenti ai rami remoti eliminati vengono rimossi automaticamente.

C’è un bel pacchetto NPM che fa per te (e dovrebbe funzionare su più piattaforms).

Installalo con: npm install -g git-removed-branches

E poi git removed-branches ti mostrerà tutti i rami locali stantii, e git removed-branches --prune per eliminarli effettivamente.

Maggiori informazioni qui.

Elencherà i rami locali il cui ramo di tracciamento remoto viene eliminato dal remoto

 $ git remote prune origin --dry-run 

Se si desidera de-fare riferimento a tali filiali locali da locali non tracciati

 $ git remote prune origin 

Se si utilizza Windows e PowerShell, è ansible utilizzare quanto segue per eliminare tutti i rami locali che sono stati uniti nel ramo attualmente estratto:

 git branch --merged | ? {$_[0] -ne '*'} | % {$_.trim()} | % {git branch -d $_} 

Spiegazione

  • Elenca il ramo corrente e i rami che sono stati uniti in esso
  • Filtra il ramo attuale
  • Pulisce gli spazi iniziali o finali dall’output git per ogni nome di ramo rimanente
  • Elimina i rami locali uniti

Vale la pena eseguire il git branch --merged da solo in primo luogo solo per assicurarsi che rimuova solo ciò che ti aspetti.

(Portato / automatizzato da http://railsware.com/blog/2014/08/11/git-housekeeping-tutorial-clean-up-outdated-branches-in-local-and-remote-repositories/ .)

Soluzione Windows

Per Microsoft Windows PowerShell:

git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Split(" ")[0]} | % {git branch -d $_}

spiegazione

git checkout master passa al ramo principale

git remote update origin --prune i rami remoti di prugne

git branch -vv ottiene un output dettagliato di tutti i rami ( git reference )

Select-String -Pattern ": gone]" ottiene solo i record in cui sono stati rimossi dal telecomando.

% { $_.toString().Split(" ")[0]} ottiene il nome del ramo

% {git branch -d $_} cancella il ramo

non sai come fare tutto in una volta, ma git git branch -d eliminerà SOLO un ramo locale se è completamente unito. Notare il d minuscolo.

git branch -D (nota la maiuscola D) cancellerà un ramo locale indipendentemente dal suo stato unito.

Volevo qualcosa che eliminasse tutte le filiali locali che stavano monitorando un ramo remoto, origin , dove il ramo remoto è stato cancellato ( gone ). Non volevo eliminare i rami locali che non erano mai stati impostati per tracciare un ramo remoto (es .: le mie filiali di sviluppo locale). Inoltre, volevo un one-liner semplice che utilizza solo git , o altri semplici strumenti CLI, piuttosto che scrivere script personalizzati. Ho finito per usare un po ‘di grep e awk per fare questo semplice comando, poi l’ho aggiunto come alias nel mio ~/.gitconfig .

 [alias] prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D 

Ecco un comando git config --global ... per aggiungere facilmente questo come git prune-branches :

 git config --global alias.prune-branches '!git remote prune origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs -r git branch -d' 

NOTA: l’uso del flag -D per git branch può essere molto pericoloso. Quindi, nel comando config sopra uso l’opzione -d per git branch piuttosto che -D ; Io uso -D nella mia configurazione attuale. Io uso -D perché non voglio sentire Git lamentarsi di rami non raggruppati, voglio solo che se ne vadano. Potresti volere anche questa funzionalità. Se è così, usa semplicemente -D invece di -d alla fine di quel comando di configurazione.

One-liner ancora più corto e più sicuro:

 git branch -d $(git branch --merged | cut -c 3-) 

Assicurati di fare il checkout al ramo che non è ancora unito, prima di eseguirlo. Perché non puoi cancellare il ramo che sei attualmente registrato.

Usando una variante sulla risposta di @ wisbucky, ho aggiunto quanto segue come alias al mio file ~/.gitconfig :

 pruneitgood = "!f() { \ git remote prune origin; \ git branch -vv | perl -nae 'system(qw(git branch -d), $F[0]) if $F[3] eq q{gone]}'; \ }; f" 

Con questo, un semplice git pruneitgood pulirà sia i rami locali che quelli remoti che non sono più necessari dopo l’unione.

In base alle risposte sopra, sono arrivato con questa soluzione a una linea:

 git remote prune origin; git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 < (git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d 

La variante di Schleis non funziona per me (Ubuntu 12.04), quindi mi permetta di proporre le mie varianti (chiare e lucide :):

Variante 1 (preferirei questa opzione):

 git for-each-ref --format='%(refname:short) %(upstream)' refs/heads/ | awk '$2 !~/^refs\/remotes/' | xargs git branch -D 

Variante 2:

un. Funzionamento a secco:

 comm -23 < ( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | awk '{print "git branch -D " $1}' 

b. Rimuovi rami:

 comm -23 < ( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | xargs git branch -D 

Ho trasformato la risposta accettata in una sceneggiatura robusta. Lo troverai nel mio repository git-extensions .

 $ git-prune --help Remove old local branches that do not exist in  any more. With --test, only print which local branches would be deleted. Usage: git-prune [-t|--test|-f|--force]  

Di seguito è riportato un adattamento della risposta di @ wisbucky per gli utenti di Windows:

for /f "tokens=1" %i in ('git branch -vv ^| findstr ": gone]"') DO git branch %i -d

Io uso posh-git e sfortunatamente a PS non piace il nudo, quindi ho creato un semplice script di comando chiamato PruneOrphanBranches.cmd:

 @ECHO OFF for /f "tokens=1" %%i in ('git branch -vv ^| findstr ": gone]"') DO CALL :ProcessBranch %%i %1 GOTO :EOF :ProcessBranch IF /I "%2%"=="-d" ( git branch %1 %2 ) ELSE ( CALL :OutputMessage %1 ) GOTO :EOF :OutputMessage ECHO Will delete branch [%1] GOTO :EOF :EOF 

Chiamalo senza parametri per visualizzare un elenco, quindi chiamalo con “-d” per eseguire la cancellazione effettiva o “-D” per tutti i rami che non sono completamente uniti ma che vuoi comunque eliminare.

Prova questo in git bash, per recuperare ed eliminare i riferimenti ai rami cancellati e quindi sfoltire i rami locali che monitoravano quelli rimossi:

 git fetch -p && git branch -d `git branch -vv | grep ': gone]' | awk '{print $1}' | xargs` 

Ricordarsi di eseguire il checkout prima di un ramo che non verrà eliminato, in modo che non blocchi l’eliminazione del ramo.

Puoi usare questo comando:

 git branch --merged master | grep -v "\* master" | xargs -n 1 git branch -d 

Git Clean: cancella i rami già uniti, inclusa l’interruzione del comando

La versione PowerShell di git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d

git branch --merged master | %{ if($_ -notmatch '\*.*master'){ git branch -d "$($_.Trim())" }}

Questo rimuoverà i rami locali che sono stati uniti in master, mentre sei nel ramo principale .

git checkout master per passare.

Elimina qualsiasi ramo che non è aggiornato con il master

 git co master && git branch | sed s/\*/\ / | xargs git branch -d 2> /dev/null 

se stai rimuovendo dal tuo computer locale , ecco il mio modo diretto :

Basta andare a: C:\Repo\your-project\.git\refs\heads

Ogni ramo è un file creato sotto questa cartella, basta rimuovere i file che corrispondono ai nomi dei tuoi rami

È difficile trovare il metodo su Windows, sto usando sourcetree e non voglio cancellarlo uno per uno. Ho appena capito in questo modo, e mi ha salvato sulla mia Windows.

Sono abbastanza sicuro che git remote prune origin sia ciò che vuoi.

Puoi eseguirlo come git remote prune origin --dry-run per vedere cosa farebbe senza apportare modifiche.

Usando la GUI? Procedura manuale, ma semplice e veloce.

 $ git gui 

Seleziona “Succursale -> Elimina”. È ansible selezionare più rami con Ctrl-clic (Windows) e rimuoverli tutti.