Come posso eliminare tutti i rami Git che sono stati uniti?


1936

Ho molti rami Git. Come posso eliminare i rami che sono già stati uniti? C'è un modo semplice per eliminarli tutti invece di eliminarli uno per uno?


46
Essere leggermente più specifici git branch -Delimina qualsiasi ramo che sia stato unito o meno.
PhilT

12
Puoi anche farlo direttamente da GitHub, se vai alla sezione 'rami' del tuo repository (ad esempio github.com/<username>/<repo_name>/branches ). Dovrebbe esserci un elenco di tutti i tuoi rami, con un'icona rossa del cestino sul lato che eliminerà il ramo selezionato. Molto più veloce di farlo nel terminale! Mostrerà anche quanto è avanti / dietro masterogni ramo. Tuttavia, il client locale elencherà comunque i vecchi rami se si esegue git branch -a; utilizzare git fetch --pruneper rimuoverli (come da questa risposta ).
user5359531

3
Script per farlo localmente o da remoto - con controlli di sicurezza e "rami sicuri" preconfigurati: github.com/fatso83/dotfiles/tree/master/utils/… git delete-merged --doit origin ogit delete-merged --doit --local
oligofren

È inoltre possibile utilizzare questa app per eliminare automaticamente i rami uniti.
Sebass van Boxel,

rm -fr work && git clone http://example.com/work.gitnel corso degli anni è diventato il modo più semplice per uscire da un sottaceto con git.
Reactgular

Risposte:


3117

AGGIORNARE:

Puoi aggiungere altri rami da escludere come master e dev se il tuo flusso di lavoro ha quelli come possibili antenati. Di solito mi dirigo da un tag "sprint-start" e master, dev e qa non sono antenati.

Innanzitutto, elenca tutti i rami che sono stati uniti in remoto.

git branch --merged

Potresti vedere alcuni rami che non vuoi rimuovere. possiamo aggiungere alcuni argomenti per saltare rami importanti che non vogliamo eliminare come master o sviluppo. Il comando seguente salterà il ramo master e tutto ciò che contiene dev.

git branch --merged| egrep -v "(^\*|master|dev)"

Se vuoi saltare, puoi aggiungerlo al comando egrep come il seguente. Il ramo skip_branch_namenon verrà eliminato.

git branch --merged| egrep -v "(^\*|master|dev|skip_branch_name)"

Per eliminare tutti i rami locali già uniti nel ramo attualmente estratto:

git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d

Puoi vedere che master e dev sono esclusi nel caso in cui siano antenati.


È possibile eliminare una filiale locale unita con:

git branch -d branchname

Se non è unito, utilizzare:

git branch -D branchname

Per eliminarlo dall'uso remoto:

git push --delete origin branchname

git push origin :branchname    # for really old git

Una volta eliminato il ramo dal telecomando, è possibile potare per eliminare i rami di tracciamento remoto con:

git remote prune origin

o potare i singoli rami di tracciamento remoto, come suggerisce l'altra risposta, con:

git branch -dr branchname

Spero che sia di aiuto.


46
ATTENZIONE: se hai appena creato un ramo, anche quello verrà eliminato. Assicurarsi di non avere un ramo appena creato nell'elenco prima di eseguire il comando più in alto.
Gary Haran,

154
OPPOSTO DI AVVERTENZA: reflog salverà la tua pancetta. Quindi non preoccuparti.
Adam Dymitruk,

33
Tieni presente che il primo comando elimina solo i rami locali, quindi non è così "pericoloso" come alcuni hanno sottolineato.
ifightcrime,

79
Variante di PowerShell, in modo che potessi trovarla qui la prossima volta che ho git branch --merged | %{$_.trim()} | ?{$_ -notmatch 'develop' -and $_ -notmatch 'master'} | %{git branch -d $_}
cercato su Google

23
Questo produce un errore fatal: branch name requiredse non ci sono rami che dovrebbero essere eliminati. Per evitare che tu possa passare -ra xargscosì non funzionerà git branch -dse lo stdin è vuoto. (Questa è un'estensione xargs GNU, secondo la pagina man).
Marius Gedminas,

457

Per eliminare tutti i rami sul telecomando già uniti:

git branch -r --merged | grep -v master | sed 's/origin\//:/' | xargs -n 1 git push origin

Nelle versioni più recenti di Git

git branch -r --merged | grep -v master | sed 's/origin\///' | xargs -n 1 git push --delete origin

AGGIORNAMENTO (di @oliver; poiché non si adatta ai commenti, ma già abbastanza risposte) : se sei sul ramo ABC, ABC apparirà nei risultati di git branch -r --mergedperché il ramo non è specificato, quindi il ramo passa automaticamente al ramo corrente e a un ramo si qualifica sempre come unito a se stesso (perché non ci sono differenze tra un ramo e se stesso!).

Quindi specifica il ramo:

git branch -r --merged master | grep -v master ...

O primo checkout master:

git checkout master | git branch -r --merged | grep -v ...

18
La migliore risposta di gran lunga. Solo una nota, il mio ramo principale è chiamato devcosì ho dovuto cambiarlo
Dorian,

41
Ho dovuto aggiungere | grep origindopo grep -v masterper evitare di spingere i rami di altri telecomandi verso l'origine. Consiglio vivamente di testare in anticipo l'output, usandogit branch -r --merged | grep -v master | grep origin | sed 's/origin\//:/' | xargs -n 1 echo
L0LN1NJ4 l'

9
Ho leggermente modificato per escludere anche il developramo. git branch -r --merged | grep -v master | grep -v develop | sed 's/origin\///' | xargs -n 1 git push --delete origin. Ora questo si è rivelato essere il mio alias.
sarat,

8
Ciò che ha reso questa la migliore risposta che ho letto, è l' -rargomento, che non ho visto menzionato altrove. È dato per scontato che valgono le pulizie solo per le filiali locali. Ma anche i telecomandi sono pieni di immondizia.
Asbjørn Ulsberg,

19
Attenzione: appena realizzato: questo ovviamente troverà i rami uniti al ramo corrente , non master, quindi se ci sei sopra myFeatureBranchcancellerai origin/myFeatureBranch. Probabilmente è meglio git checkout masterprima di tutto.
jakub.g,

190

Estendendo un po 'la risposta di Adam:

Aggiungi questo alla tua configurazione Git eseguendo git config -e --global

[alias]
    cleanup = "!git branch --merged | grep  -v '\\*\\|master\\|develop' | xargs -n 1 git branch -d"

E poi puoi eliminare tutti i rami uniti locali facendo un semplice git cleanup.


11
il primo comando non dovrebbe essere: git branch --merged masterdal momento che si desidera esaminare ciò che è stato unito nel master, non è attualmente il ramo estratto?
Joe Phillips,

@JoePhilllips Alcune persone hanno il ramo principale non master ma invece developo deve in quel caso il comando fallirà con fatal: malformed object nameè meglio avere un comando generico e hai la responsabilità di eseguirlo
smohamed

1
@JoePhilllips il punto di questa risposta è impacchettare la risposta di Adam (la risposta migliore per questa domanda) in utile alias git. La risposta di Adam non ha quello che stai suggerendo e così tante persone lo hanno trovato utile, quindi sarei propenso a non cambiare il mio. Consiglierei di aprire la discussione sulla risposta di Adam se ti senti fortemente al riguardo
real_ate

13
L'aggiunta -ra xargsimpedisce errori inutili ( branch name required) quando si esegue questo alias più volte o quando non è rimasto alcun ramo da eliminare. Il mio alias è simile al seguente:cleanup = "!git branch --merged | grep -v -P '^\\*|master|develop' | xargs -n1 -r git branch -d"
spezifanta,

1
Il comando corrente non filtra il master e sviluppa i rami
Andriy F.

83

Questo funziona anche per eliminare tutti i rami uniti tranne master.

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

3
Ora non cancellerà alcun ramo con masteral suo interno. Prova grep -v ^master$per il mezzo.
wchargin,

| grep -v '^\*'Lascerei anche evitare di cancellare il ramo corrente se non si è in master
svassr

5
Questo è fantastico, grazie! Un avvertimento per chiunque usi questo: nota che ci sono due spazi dentro grep -v '^ master$'. Se lo digiti in te stesso e ne manchi uno, lo eliminerai masterse non ci sei.
Styger,

3
@ Mr.Polywhirl la tua modifica interrompe il comando e dovresti ripristinarlo. I due spazi sono necessari, poiché git branchelencherà il nome di ciascun ramo su una nuova riga con due spazi a sinistra se non è il ramo attualmente estratto. In sostanza, hai garantito che chiunque eseguirà questo comando eliminerà il proprio ramo principale a meno che non sia il ramo attualmente estratto.
Styger

79

Ti consigliamo di escludere i rami master& developda quei comandi.

Git locale chiaro:

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

Cancella da remoto:

git branch -r --merged | grep -v '\*\|master\|develop' | sed 's/origin\///' | xargs -n 1 git push --delete origin

Sincronizza il registro locale delle filiali remote:

git fetch -p

3
+1 anche per la versione remota (ma meno necessaria in quanto abbiamo --prune remota). Vale anche la pena notare che thoose non funzionerà con la versione precedente di git
malko l'

4
git config --global --add fetch.prune trueper potare automaticamente al recupero o tirare.
T3rm1,

1
Intendiamoci, la prugna non è la stessa della cancellazione remota. La cancellazione remota elimina effettivamente i rami remoti che sono completamente uniti al ramo corrente. Prune pulisce solo il registro locale dei rami remoti che sono già stati eliminati.
Guido Bouman,

La parola completamente è un po 'fuorviante, poiché un ramo sarà considerato unito, quando è stato unito prima, ma ha nuovi commit dopo l'unione, che non sono stati uniti.
focaccine

Per eliminare tutti i telecomandi di origine in una chiamata, ho usato questo:git branch -r --merged | grep -v '\*\|master\|develop' | grep '^\s*origin/' | sed 's/origin\///' | tr "\n" " " | xargs git push --delete origin
GPHemsley,

48

Per quelli di voi che si trovano su Windows e preferiscono gli script PowerShell, eccone uno che elimina i rami uniti locali:

function Remove-MergedBranches
{
  git branch --merged |
    ForEach-Object { $_.Trim() } |
    Where-Object {$_ -NotMatch "^\*"} |
    Where-Object {-not ( $_ -Like "*master" )} |
    ForEach-Object { git branch -d $_ }
}

13
Per motivi di curiosità, questo può essere abbreviato in git branch --merged | ?{-not ($_ -like "*master")} | %{git branch -d $_.trim()}
Iain Ballard

5
@IainBallard Certo, avrei potuto usare gli alias. Questo non è raccomandato quando si desidera massimizzare la leggibilità. github.com/darkoperator/PSStyleGuide/blob/master/English.md
Klas Mellbourn

1
sicuro. Ho trovato la tua risposta molto utile :-) Tuttavia, a volte la sintassi di PowerShell long-form ostacola ciò che sta accadendo nei blocchi. Ma principalmente, stavo proponendo qualcosa che potresti copiare / incollare o digitare come una tantum. Grazie ancora.
Iain Ballard,

4
Ecco un one-liner per la shell cmd di Windows che preserva master e il tuo ramo corrente: for /f "usebackq" %B in (``git branch --merged^|findstr /v /c:"* " /c:"master"``) do @git branch -d %B(sospira, sostituisci i doppi backquotes con single, non sono sicuro di come formattare un letterale che contenga backquotes)
yoyo

42

Ho usato la risposta di Adam per anni ormai. Detto questo, ci sono alcuni casi in cui non si stava comportando come mi aspettavo:

  1. rami che contenevano la parola "maestro" sono stati ignorati, ad esempio "notmaster" o "masterful", piuttosto che solo il ramo master
  2. rami che contenevano la parola "dev" venivano ignorati, ad esempio "dev-test", piuttosto che solo il ramo dev
  3. eliminazione di rami raggiungibili dall'HEAD del ramo corrente (ovvero, non necessariamente master)
  4. nello stato HEAD distaccato, eliminando tutti i rami raggiungibili dal commit corrente

1 e 2 erano semplici da affrontare, con solo una modifica alla regex. 3 dipende dal contesto di ciò che si desidera (ovvero eliminare solo i rami che non sono stati uniti in master o rispetto al ramo corrente). 4 ha il potenziale per essere disastroso (anche se recuperabile con git reflog), se lo hai eseguito involontariamente in stato HEAD distaccato.

Alla fine, volevo che tutto questo fosse in una riga che non richiedeva uno script separato (Bash | Ruby | Python).

TL; DR

Crea un alias git "sweep" che accetta un -fflag opzionale :

git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'

e invocalo con:

git sweep

o:

git sweep -f

La risposta lunga e dettagliata

È stato più semplice per me creare un repository git di esempio con alcuni rami e si impegna a testare il comportamento corretto:

Crea un nuovo repository git con un unico commit

mkdir sweep-test && cd sweep-test && git init
echo "hello" > hello
git add . && git commit -am "initial commit"

Crea alcuni nuovi rami

git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterful
git branch --list
  bar
  develop
  foo
* master
  masterful
  notmaster

Comportamento desiderato: selezionare tutti i rami uniti tranne: master, sviluppo o corrente

Il regex originale manca i rami "magistrale" e "notmaster":

git checkout foo
git branch --merged | egrep -v "(^\*|master|dev)"
  bar

Con il regex aggiornato (che ora esclude "sviluppo" anziché "dev"):

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster

Passa al ramo foo, effettua un nuovo commit, quindi verifica un nuovo ramo, foobar, basato su foo:

echo "foo" > foo
git add . && git commit -am "foo"
git checkout -b foobar
echo "foobar" > foobar
git add . && git commit -am "foobar"

Il mio ramo attuale è foobar, e se riesco a eseguire nuovamente il comando sopra per elencare i rami che voglio eliminare, il ramo "pippo" è incluso anche se non è stato unito al master:

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  foo
  masterful
  notmaster

Tuttavia, se eseguo lo stesso comando sul master, il ramo "pippo" non è incluso:

git checkout master && git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

E questo semplicemente perché il git branch --mergedvalore predefinito è HEAD del ramo corrente se non diversamente specificato. Almeno per il mio flusso di lavoro, non voglio eliminare i rami locali a meno che non siano stati uniti al master, quindi preferisco la seguente variante:

git checkout foobar
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

Stato HEAD distaccato

Affidarsi al comportamento predefinito di git branch --mergedha conseguenze ancora più significative nello stato HEAD distaccato:

git checkout foobar
git checkout HEAD~0
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  foo
  foobar
  masterful
  notmaster

Ciò avrebbe cancellato il ramo in cui mi trovavo, "foobar" insieme a "foo", che non è quasi certamente il risultato desiderato. Con il nostro comando rivisto, tuttavia:

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

Una riga, incluso l'eliminazione effettiva

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" | xargs git branch -d

Tutto racchiuso in una "spazzata" alias git:

git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'

L'alias accetta un -fflag opzionale . Il comportamento predefinito consiste nell'eliminare solo i rami che sono stati uniti nel master, ma il -fflag eliminerà i rami che sono stati uniti nel ramo corrente.

git sweep
Deleted branch bar (was 9a56952).
Deleted branch masterful (was 9a56952).
Deleted branch notmaster (was 9a56952).
git sweep -f
Deleted branch foo (was 2cea1ab).

Perché è necessario creare una funzione? Non è git configatomico?
VasiliNovikov,

Per affrontare l'argomento facoltativo '-f' (se capisco correttamente la tua domanda)
vaga il

1
ma come aiuta? Voglio dire l'inizio dell'espressione, !f(){ git branch .... È una dichiarazione di funzione, giusto? Perché non iniziare direttamente con git branch ...?
VasiliNovikov

1
Hai assolutamente ragione. Modificato la mia risposta di conseguenza. Grazie per il puntatore!
vortici il

Quanto segue non farebbe lo stesso della modalità non forzata? git checkout master && git branch -d `git branch --merged` && git checkout - Tranne che si eliminerebbe develop, ma potrebbe essere un approccio più semplice.
Guido Bouman,


18

Utilizzando Git versione 2.5.0:

git branch -d `git branch --merged`

16
Questo può cancellare il masterramo tra l'altro!
Wazery,

4
Vero. Lo uso solo quando sono sicuro di essere acceso master.
drautb

11
git branch -d $(git branch --merged | grep -v master)
alexg

1
Questo è pericoloso se hai un flusso, immagina di avere il master <- stage <- dev. Soluzione ancora più semplice imo
Joseph Briggs

14

È possibile aggiungere il commit all'opzione --merged. In questo modo puoi assicurarti di rimuovere solo i rami che sono uniti in origine / master

Il comando seguente rimuoverà i rami uniti dalla tua origine.

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 git push origin --delete 

Puoi testare quali rami verranno rimossi sostituendo l'origine push git - cancella con eco

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo

2
Mi piace l'opzione di test
iwein

12

Uso il seguente script Ruby per eliminare i miei rami locali e remoti già uniti. Se lo sto facendo per un repository con più telecomandi e desidero solo eliminarne uno, aggiungo semplicemente un'istruzione select all'elenco dei telecomandi per ottenere solo i telecomandi che desidero.

#!/usr/bin/env ruby

current_branch = `git symbolic-ref --short HEAD`.chomp
if current_branch != "master"
  if $?.exitstatus == 0
    puts "WARNING: You are on branch #{current_branch}, NOT master."
  else
    puts "WARNING: You are not on a branch"
  end
  puts
end

puts "Fetching merged branches..."
remote_branches= `git branch -r --merged`.
  split("\n").
  map(&:strip).
  reject {|b| b =~ /\/(#{current_branch}|master)/}

local_branches= `git branch --merged`.
  gsub(/^\* /, '').
  split("\n").
  map(&:strip).
  reject {|b| b =~ /(#{current_branch}|master)/}

if remote_branches.empty? && local_branches.empty?
  puts "No existing branches have been merged into #{current_branch}."
else
  puts "This will remove the following branches:"
  puts remote_branches.join("\n")
  puts local_branches.join("\n")
  puts "Proceed?"
  if gets =~ /^y/i
    remote_branches.each do |b|
      remote, branch = b.split(/\//)
      `git push #{remote} :#{branch}`
    end

    # Remove local branches
    `git branch -d #{local_branches.join(' ')}`
  else
    puts "No branches removed."
  end
end

Ti dispiace se rubo questo bocconcino per una piccola libreria di aiuto git? github.com/yupiq/git-branch-util
logan

1

@mmrobins Hai un extra \/all'inizio della dichiarazione di rifiuto per la remote_branchesriga. È un errore di battitura o serve a uno scopo?
Jawwad,

@mmrobins, oh non importa, ora vedo la b.split(/\//)riga
Jawwad,

Se vuoi fare sostanzialmente questo, ma tramite vanilla bash piuttosto che ruby: stackoverflow.com/a/37999948/430128
Raman,

11

Come eliminare i rami uniti nella console di PowerShell

git branch --merged | %{git branch -d $_.Trim()}

Se si desidera escludere i nomi master o qualsiasi altro ramo, è possibile eseguire il pipe con PowerShell Select-String in questo modo e passare il risultato a git branch -d:

git branch -d $(git branch --merged | Select-String -NotMatch "master" | %{$_.ToString().Trim()})

1
Risposte più alte suggeriscono il filtro master o altri rami. Per coloro che desiderano farlo in PowerShell: git branch --merged | findstr / v "master" | % {git branch -d $ _. trim ()}
tredzko

@tredzko Un buon punto. FTR la risposta più alta è stackoverflow.com/questions/6127328/… - potresti ripubblicare il tuo commento con quello collegato e poi lo cancellerei
Ruben Bartelink

tenta anche di eliminare * master:)
ovvero il

9

La risposta di kuboon non è riuscita a eliminare i rami che hanno la parola master nel nome del ramo. Quanto segue migliora la sua risposta:

git branch -r --merged | grep -v "origin/master$" | sed 's/\s*origin\///' | xargs -n 1 git push --delete origin

Naturalmente, non elimina il ramo "master" stesso :)


8

Non esiste alcun comando in Git che lo farà automaticamente. Ma puoi scrivere uno script che utilizza i comandi Git per darti ciò di cui hai bisogno. Questo potrebbe essere fatto in molti modi a seconda del modello di diramazione che stai utilizzando.

Se devi sapere se un ramo è stato unito in master, il comando seguente non produrrà alcun output se myTopicBranch è stato unito (ovvero puoi eliminarlo)

$ git rev-list master | grep $(git rev-parse myTopicBranch)

Puoi usare il comando Git branch e analizzare tutti i rami in Bash e fare un forciclo su tutti i rami. In questo ciclo si controlla con il comando sopra se è possibile eliminare il ramo o meno.



7

Nota : non sono soddisfatto delle risposte precedenti, (non funziona su tutti i sistemi, non funziona su remoto, non specifica il ramo --merged, non filtra esattamente). Quindi, aggiungo la mia risposta.

Esistono due casi principali:

Locale

Si desidera eliminare i rami locali che sono già uniti a un altro ramo locale . Durante la cancellazione, vuoi mantenere alcuni rami importanti, come master, sviluppare, ecc.

git branch --format "%(refname:short)" --merged master | grep -E -v '^master$|^feature/develop$' | xargs -n 1 git branch -d

Note :

  • git branch output --format ".." significa eliminare gli spazi bianchi e consentire la corrispondenza esatta del grep
  • grep -Eviene usato al posto di egrep , quindi funziona anche in sistemi senza egrep (es. git per windows).
  • grep -E -v '^master$|^feature/develop$' è specificare i rami locali che non voglio cancellare
  • xargs -n 1 git branch -d: esegue la cancellazione delle filiali locali (non funzionerà per quelle remote)
  • ovviamente viene visualizzato un errore se si tenta di eliminare il ramo attualmente estratto. Quindi, suggerisco di passare prima al master.

A distanza

Si desidera eliminare i rami remoti che sono già uniti a un altro ramo remoto . Durante la cancellazione, vuoi mantenere alcuni rami importanti, come HEAD, master, release, ecc.

git branch -r --format "%(refname:short)" --merged origin/master | grep -E -v '^*HEAD$|^*/master$|^*release' | cut -d/ -f2- | xargs -n 1 git push --delete origin

Note :

  • per remoto, utilizziamo l' -ropzione e forniamo il nome completo della filiale :origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release' è abbinare i rami remoti che non vogliamo eliminare.
  • cut -d/ -f2-: rimuove il prefisso 'origin /' non necessario che altrimenti verrà stampato dal git branchcomando.
  • xargs -n 1 git push --delete origin : esegue la cancellazione di filiali remote.

7

Se sei su Windows puoi usare Windows Powershell o Powershell 7 con Out-GridView per avere un buon elenco di rami e selezionare con il mouse quale vuoi eliminare:

git branch --format "%(refname:short)" --merged  | Out-GridView -PassThru | % { git branch -d $_ }

inserisci qui la descrizione dell'immagine dopo aver fatto clic su OK Powershell passerà i nomi di questi rami per git branch -dcomandarli ed eliminarli inserisci qui la descrizione dell'immagine


6

Puoi usare lo git-del-br strumento .

git-del-br -a

Puoi installarlo pipusando

pip install git-del-br

PS: sono l'autore dello strumento. Eventuali suggerimenti / feedback sono benvenuti.


1
@ stackoverflow.com/users/100297/martijn-pieters : Perché questa risposta è stata cancellata e sottoposta a downgrade?
tusharmakkar08,

1
La tua risposta e il tuo strumento non funzionano. Ci passo un paio d'ore. Niente.
SpoiledTechie.com,

@ SpoiledTechie.com: puoi dirmi quale problema stai affrontando esattamente? Lo sto usando su base regolare.
tusharmakkar08,

Posso condividere uno screenshot se vuoi metterlo offline? spoiledtechie a quella cosa di google mail. :)
SpoiledTechie.com il

5

Se desideri eliminare tutti i rami locali che sono già uniti al ramo in cui ti trovi attualmente, ho trovato un comando sicuro per farlo, basato su risposte precedenti:

git branch --merged | grep -v \* | grep -v '^\s*master$' | xargs -t -n 1 git branch -d

Questo comando non influirà sul ramo corrente o sul ramo principale. Ti dirà anche cosa sta facendo prima di farlo, usando il flag -t di xargs.


5

Versione alias della risposta aggiornata di Adam :

[alias]
    branch-cleanup = "!git branch --merged | egrep -v \"(^\\*|master|dev)\" | xargs git branch -d #"

Inoltre, vedi questa risposta per consigli utili su come sfuggire a alias complessi.


5

Uso uno schema di denominazione esque git-flow, quindi questo funziona in modo molto sicuro per me:

git branch --merged | grep -e "^\s\+\(fix\|feature\)/" | xargs git branch -d

Fondamentalmente cerca commit uniti che iniziano con una stringa fix/o feature/.


4

Prova il seguente comando:

git branch -d $(git branch --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

Usando git rev-parseotterrà il nome del ramo corrente per escluderlo. Se ricevi l'errore, significa che non ci sono filiali locali da rimuovere.

Per fare lo stesso con i rami remoti (cambia origincon il tuo nome remoto), prova:

git push origin -vd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD) | cut -d/ -f2)

Se hai più telecomandi, aggiungi grep origin |prima cutper filtrare solo il origin.

Se il comando precedente non riesce, prova prima a eliminare i rami di tracciamento remoto uniti:

git branch -rd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

Quindi di git fetchnuovo il telecomando e utilizzare di nuovo il git push -vdcomando precedente .

Se lo usi spesso, considera l'aggiunta come alias nel tuo ~/.gitconfigfile.

Nel caso in cui tu abbia rimosso alcuni rami per errore, usa git reflogper trovare i commit persi.


4

Sulla base di alcune di queste risposte ho creato anche il mio script Bash per farlo !

Utilizza git branch --mergede git branch -dper eliminare i rami che sono stati uniti e richiede di inserire tutti i rami prima di eliminarli.

merged_branches(){
  local current_branch=$(git rev-parse --abbrev-ref HEAD)
  for branch in $(git branch --merged | cut -c3-)
    do
      echo "Branch $branch is already merged into $current_branch."
      echo "Would you like to delete it? [Y]es/[N]o "
      read REPLY
      if [[ $REPLY =~ ^[Yy] ]]; then
        git branch -d $branch
      fi
  done
}

4

Di seguito la query funziona per me

for branch in  `git branch -r --merged | grep -v '\*\|master\|develop'|awk 'NR > 0 {print$1}'|awk '{gsub(/origin\//, "")}1'`;do git push origin --delete $branch; done

e questo filtrerà qualsiasi ramo dato nel tubo grep.

Funziona bene su clone http, ma non così bene per la connessione ssh.


4

A partire da 2018.07

Aggiungi questo alla [alias]sezione del tuo ~/.gitconfig:

sweep = !"f() { git branch --merged | egrep -v \"(^\\*|master|dev)\" || true | xargs git branch -d; }; f"

Ora puoi semplicemente chiamare git sweepper eseguire la pulizia necessaria.


Per me, chiamare git sweep elenca solo i rami che dovrebbero essere ripuliti, ma non li rimuove
Victor Moraes,

4

Su Windows con git bash installato egrep -v non funzionerà

git branch --merged | grep -E -v "(master|test|dev)" | xargs git branch -d

dove grep -E -vè equivalente aegrep -v

Utilizzare -dper rimuovere già fuse rami o -Dper rimuovere unmerged rami


egrep -v funziona per me. Sto usando gitbash dall'installer di gitextensions però
Joe Phillips,

4

Ho usato il seguente metodo per rimuovere i rami AND AND locali uniti in un cmd.

Ho il seguente nel mio bashrcfile:

function rmb {
  current_branch=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
  if [ "$current_branch" != "master" ]; then
    echo "WARNING: You are on branch $current_branch, NOT master."
  fi
  echo "Fetching merged branches..."
  git remote prune origin
  remote_branches=$(git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$")
  local_branches=$(git branch --merged | grep -v 'master$' | grep -v "$current_branch$")
  if [ -z "$remote_branches" ] && [ -z "$local_branches" ]; then
    echo "No existing branches have been merged into $current_branch."
  else
    echo "This will remove the following branches:"
    if [ -n "$remote_branches" ]; then
      echo "$remote_branches"
    fi
    if [ -n "$local_branches" ]; then
      echo "$local_branches"
    fi
    read -p "Continue? (y/n): " -n 1 choice
    echo
    if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
      # Remove remote branches
      git push origin `git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$" | sed 's/origin\//:/g' | tr -d '\n'`
      # Remove local branches
      git branch -d `git branch --merged | grep -v 'master$' | grep -v "$current_branch$" | sed 's/origin\///g' | tr -d '\n'`
    else
      echo "No branches removed."
    fi
  fi
}

fonte originale

Ciò non elimina il ramo principale, ma rimuove i rami locali AND remoti uniti . Una volta che hai questo nel tuo file rc, basta eseguirlo rmb, ti viene mostrato un elenco di rami uniti che verranno ripuliti e verrà chiesta conferma sull'azione. Puoi modificare il codice per non chiedere conferma, ma probabilmente è bene tenerlo.


3

Scrivi uno script in cui Git verifica tutti i rami che sono stati uniti al master.

Allora fallo git checkout master.

Infine, elimina i rami uniti.

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git checkout $branchnew
done

git checkout master

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git push origin --delete $branchnew
done

3

La soluzione accettata è piuttosto buona, ma ha l'unico problema di eliminare anche le filiali locali che non sono state ancora unite in un telecomando.

Se guardi l'output di vedrai qualcosa di simile

$ git branch --merged master -v
  api_doc                  3a05427 [gone] Start of describing the Java API
  bla                      52e080a Update wording.
  branch-1.0               32f1a72 [maven-release-plugin] prepare release 1.0.1
  initial_proposal         6e59fb0 [gone] Original proposal, converted to AsciiDoc.
  issue_248                be2ba3c Skip unit-for-type checking. This needs more work. (#254)
  master                   be2ba3c Skip unit-for-type checking. This needs more work. (#254)

Rami blae issue_248sono rami locali che verrebbero eliminati silenziosamente.

Ma puoi anche vedere la parola [gone], che indica i rami che erano stati spinti su un telecomando (che ora non c'è più) e che quindi indicano che i rami possono essere eliminati.

La risposta originale può quindi essere cambiata in (divisa in multilinea per una lunghezza della linea più breve)

git branch --merged master -v | \
     grep  "\\[gone\\]" | \
     sed -e 's/^..//' -e 's/\S* .*//' | \
      xargs git branch -d

per proteggere i rami non ancora uniti. Anche il grepping per master per proteggerlo, non è necessario, poiché questo ha un telecomando all'origine e non si presenta come andato.


3

Per me git branch --mergednon mostra filiali che sono state unite tramite GitHub PR. Non sono sicuro dei motivi, ma utilizzo la seguente riga per eliminare tutti i rami locali che non hanno un ramo di tracciamento remoto :

diff <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | grep '<' | cut -c 3- | xargs git branch -D

Spiegazione:

  • git branch --format "%(refname:short)" fornisce un elenco di filiali locali
  • git branch -r | grep -v HEAD | cut -d/ -f2- fornisce un elenco di rami remoti, filtrando HEAD
  • diff <(...) <(...) fornisce una differenza di output di due comandi tra parentesi
  • grep '<' filtra i rami esistenti nel primo elenco, ma non nel secondo
  • cut -c 3- restituisce una riga a partire dal terzo carattere, rimuovendo così il prefisso <
  • xargs git branch -Dviene eseguito in git branch -Dbase al nome di ciascun ramo

In alternativa, puoi evitare in grep -v '<'questo modo:

diff --old-line-format="%L" --new-line-format="" --unchanged-line-format="" <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | xargs git branch -D
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.