2013-03-27 7 views
37

Problema: desidero un modo per eliminare tutti i rami locali che non dispongono di un telecomando. È abbastanza facile convogliare i nomi dei rami in un git branch -D {branch_name}, ma come faccio a ottenere quell'elenco in primo luogo?Elenco di tutte le filiali locali senza un telefono

Ad esempio:

ho creare un nuovo ramo senza telecomando:

$ git co -b no_upstream 

vi elenco tutti i miei rami, c'è solo 1 con un telecomando

$ git branch -a 
master 
* no_upstream 
remotes/origin/HEAD -> origin/master 
remotes/origin/master 

Quale comando posso correre a ottenere no_upstream come risposta?

posso correre git rev-parse --abbrev-ref --symbolic-full-name @{u} e che mostrerà che non ha alcun remoto:

$ git rev-parse --abbrev-ref --symbolic-full-name @{u} 
error: No upstream configured for branch 'no_upstream' 
error: No upstream configured for branch 'no_upstream' 
fatal: ambiguous argument '@{u}': unknown revision or path not in the working tree. 
Use '--' to separate paths from revisions, like this: 
'git <command> [<revision>...] -- [<file>...]' 

Ma come questo è un errore, non mi permette di usarlo o pipe ad altri comandi. Ho intenzione di utilizzare questo come uno script di shell alias'd a git-delete-unbranched o forse fare una gemma super semplice come git-branch-delete-orphans

Qualsiasi aiuto sarebbe apprezzato! Grazie

+0

Vedere anche http://stackoverflow.com/questions/4950725/how-do-i-get-git-to-show-me-which-branches-are-tracking-what –

+1

Possibile duplicato di [Rimuovi rami locali non più sul telecomando] (http://stackoverflow.com/questions/7726949/remove-local-branches-no-longer-on-remote) – ks1322

risposta

19

git branch (senza alcuna opzione) elenca solo i rami locali, ma non si sa se tracciano un ramo remoto o no.

Di solito quei rami locali va cancellato una volta fusi in master (come si vede nella this issue of git-sweep):

git branch --merged master | grep -v master | xargs git branch -d 

Questo non è completo come si vuole, ma è un inizio.

Con --merged, solo rami fuse nel nome commit (vale a dire i rami la cui punta impegna sono raggiungibili dal nome commit) saranno elencati.

+0

Per includere anche i rami remoti senza un ramo locale, utilizzare 'git branch -a - -merged'. –

13

tardo edit: meglio è

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

su GNU/niente

for b in `git branch|sed s,..,,`; do 
    git config --get branch.$b.remote|sed Q1 && echo git branch -D $b 
done 

Se più di una manciata di rami sono stati probabilmente ci sarebbe modi migliori, utilizzando comm -23 sull'uscita di git branch|sed|sort e git config -l|sed|sort.

+0

Sembra più preciso della mia risposta. +1 – VonC

+0

Qualcuno sa quale potrebbe essere l'equivalente del comando BSD sed? – nmr

+1

@nmr s/git. * Q1/test $ (git config --get branch. $ B.remote | sed q | wc -1) = 1/ – jthill

2

approssimativa implementazione PowerShell: (se il carattere originario è l'unica a distanza)

@($branches = git br -r; git branch | %{ echo $_ | sed 's/..//' }) ` 
    | %{ if (($branches | ss "origin/$_") -eq $null) { ` 
      echo "git branch -D $_" ` 
     } ` 
     } 
+0

Piuttosto che scaricare una porzione di codice, è utile spiegare come le parti funzionano (quindi gli altri si adattano se hanno esigenze simili ma non precise). – MrFlick

+0

O almeno formatta in modo che le persone possano vederlo tutto. Lo farei ma non conosco la continuazione della linea di PowerShell. Detto questo, 'sed' su windows non può fare' s, .. ,, '? Ha davvero bisogno di tutto questo? e: dov'è il test per un vuoto '$ X'? – jthill

42

recente ho scoperto git branch -vv che è la versione "molto verboso" del comando git branch.

Emette i rami con le filiali remote, se esistono, nel seguente formato:

25-timeout-error-with-many-targets 206a5fa WIP: batch insert 
    31-target-suggestions     f5bdce6 [origin/31-target-suggestions] Create target suggestion for team and list on save 
* 54-feedback-link      b98e97c [origin/54-feedback-link] WIP: Feedback link in mail 
    65-digest-double-publish    2de4150 WIP: publishing-state 

Una volta che hai questa uscita ben formattata, è facile come tubazioni attraverso cut e awk per ottenere la vostra lista:

git branch -vv | cut -c 3- | awk '$3 !~/\[/ { print $1 }' 

risultati nel seguente output:

25-timeout-error-with-many-targets 
65-digest-double-publish 

La parte cut normalizza semplicemente i dati rimuovendo i primi due caratteri (incluso *) dall'output prima di passarli a awk.

La parte awk stampa la prima colonna se non vi è alcuna parentesi quadra nella terza colonna.

Bonus: Creare un alias

lo rendono facile da eseguire con la creazione di un alias nel .gitconfig file globale (o dovunque):

[alias] 
    local-branches = !git branch -vv | cut -c 3- | awk '$3 !~/\\[/ { print $1 }' 

Importante: la barra rovesciata deve essere sfuggito a l'alias altrimenti avremo un file gitconfig non valido.

Bonus: Remote Filtering

Se per qualche ragione si dispone di più telecomandi di monitoraggio per i diversi rami, è abbastanza facile per specificare che a distanza si desidera controllare contro. Basta aggiungere il nome remoto allo schema di awk. Nel mio caso, è origin così posso fare questo:

git branch -vv | cut -c 3- | awk '$3 !~/\[origin/ { print $1 }' 
+0

questa cosa ha anche elencato lo sviluppo e le filiali principali .. egh .. – igrek

+0

che cosa 'WIP:' comunque ...? non è quello che crea un comando stash ..? – igrek

+0

@igrek Questo è solo un prefisso che ho usato nel messaggio di commit. Niente di specifico per git. –

10

Ho un problema simile. Voglio rimuovere tutti i rami locali che stavano monitorando i rami remoti che sono ora cancellati. Sto scoprendo che git remote prune origin non è stato sufficiente per rimuovere i rami che voglio siano andati. Una volta che il telecomando è stato eliminato, voglio che anche il locale se ne vada. Ecco che cosa ha funzionato per me:

Dal mio ~/.gitconfig:

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

EDIT: Come richiesto, 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 : Ho cambiato il -d in -D nella mia configurazione attuale perché non voglio sentire Git lamentarsi di rami non raggruppati . Si può desidera anche questa funzionalità. In tal caso, utilizzare semplicemente -D anziché -d alla fine di tale comando.

Inoltre, FWIW, il tuo file di configurazione globale sarebbe quasi sempre ~/.gitconfig.

+1

È possibile convertire questo in un comando "git config --global ..."? Da un punto di vista istruzioni/how-to-wiki-for-dummies è facile da trasmettere invece di dire "Trova i tuoi file di configurazione git, usa l'editor per modificarlo e poi esegui i comandi" –

5

questo funziona per me:

git branch -vv | grep -v origin

(Se il telecomando si chiama qualcosa di diverso origine, sostituire tale).

Questo elencherà tutti i rami che non stanno monitorando un telecomando, che suona come quello che stai cercando.

+0

Questo elencherà i rami che erano soliti avere un telecomando ma non farlo più neanche se si esegue 'git fetch --prune'. – RusinaRange