Wie kann ich alle zusammengeführten Git-Zweige löschen?

1935

Ich habe viele Git-Zweige. Wie lösche ich bereits zusammengeführte Zweige? Gibt es eine einfache Möglichkeit, sie alle zu löschen, anstatt sie einzeln zu löschen?

Nyambaa
quelle
46
Um etwas genauer zu sein, wird git branch -Djeder Zweig gelöscht, unabhängig davon, ob er zusammengeführt wurde oder nicht.
PhilT
12
Sie können dies auch direkt von GitHub aus tun, wenn Sie zum Abschnitt "Zweige" Ihres Repos gehen (z . B. github.com/<Benutzername>/<Repo-Name>/Zweige ). Es sollte eine Liste aller Ihrer Zweige mit einem roten Papierkorbsymbol an der Seite vorhanden sein, mit dem der ausgewählte Zweig gelöscht wird. Viel schneller als im Terminal! Zeigt auch an, wie weit vor / hinter masterjedem Zweig ist. Ihr lokaler Client listet jedoch weiterhin die alten Zweige auf, wenn Sie ausgeführt werden git branch -a. Verwenden Sie git fetch --prune, um sie zu entfernen (gemäß dieser Antwort ).
user5359531
3
Skript, um dies lokal oder remote zu tun - mit Sicherheitsüberprüfungen und vorkonfigurierten "sicheren Zweigen": github.com/fatso83/dotfiles/tree/master/utils/… git delete-merged --doit origin odergit delete-merged --doit --local
oligofren
Sie können diese App auch verwenden , um zusammengeführte Zweige automatisch zu löschen.
Sebass van Boxel
rm -fr work && git clone http://example.com/work.gitIm Laufe der Jahre ist es der einfachste Weg geworden, mit Git aus einer Gurke herauszukommen.
Reactgular

Antworten:

3115

AKTUALISIEREN:

Sie können andere Zweige hinzufügen, um Master und Entwickler auszuschließen, wenn Ihr Workflow diese als möglichen Vorfahren hat. Normalerweise verzweige ich von einem "Sprint-Start" -Tag und Master, Dev und Qa sind keine Vorfahren.

Listen Sie zunächst alle Zweige auf, die in Remote zusammengeführt wurden.

git branch --merged

Möglicherweise sehen Sie einige Zweige, die Sie nicht entfernen möchten. Wir können einige Argumente hinzufügen, um wichtige Zweige zu überspringen, die wir nicht löschen möchten, wie z. B. Master oder Entwicklung. Der folgende Befehl überspringt den Hauptzweig und alles, was dev enthält.

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

Wenn Sie überspringen möchten, können Sie es wie folgt zum Befehl egrep hinzufügen. Der Zweig skip_branch_namewird nicht gelöscht.

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

So löschen Sie alle lokalen Zweige, die bereits mit dem aktuell ausgecheckten Zweig zusammengeführt wurden:

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

Sie können sehen, dass Master und Dev ausgeschlossen sind, falls sie ein Vorfahr sind.


Sie können einen zusammengeführten lokalen Zweig löschen mit:

git branch -d branchname

Wenn es nicht zusammengeführt wird, verwenden Sie:

git branch -D branchname

So löschen Sie es von der Remote-Verwendung:

git push --delete origin branchname

git push origin :branchname    # for really old git

Sobald Sie den Zweig von der Fernbedienung gelöscht haben, können Sie ihn entfernen, um Fernverfolgungszweige zu entfernen:

git remote prune origin

oder beschneiden Sie einzelne Fernverfolgungszweige, wie die andere Antwort andeutet, mit:

git branch -dr branchname

Hoffe das hilft.

Adam Dymitruk
quelle
46
WARNUNG: Wenn Sie gerade einen Zweig erstellt haben, wird dieser ebenfalls gelöscht. Stellen Sie sicher, dass die Liste keinen neu erstellten Zweig enthält, bevor Sie den Befehl am häufigsten ausführen.
Gary Haran
153
GEGENÜBER DER WARNUNG: Reflog spart Ihren Speck. Also mach dir keine Sorgen.
Adam Dymitruk
33
Beachten Sie, dass der erste Befehl nur lokale Zweige löscht, sodass er nicht so gefährlich ist, wie einige darauf hingewiesen haben.
ifightcrime
79
PowerShell-Variante, damit ich sie beim nächsten Mal hier finden konnte, googelte ich die Antwort:git branch --merged | %{$_.trim()} | ?{$_ -notmatch 'develop' -and $_ -notmatch 'master'} | %{git branch -d $_}
vorou
23
Dies führt zu einem Fehler, fatal: branch name requiredwenn Sie keine Zweige haben, die gelöscht werden sollen. Um dies zu vermeiden, können Sie an übergeben -r, xargsdamit es nicht ausgeführt wird, git branch -dwenn der Standard leer ist. (Dies ist eine GNU xargs-Erweiterung, laut Manpage).
Marius Gedminas
457

So löschen Sie alle Zweige auf der Fernbedienung, die bereits zusammengeführt wurden:

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

In neueren Versionen von Git

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

UPDATE (von @oliver; da passt nicht in einen Kommentar, aber es gibt bereits genügend Antworten) : Wenn Sie sich in Zweig ABC befinden, wird ABC in den Ergebnissen von angezeigt, dagit branch -r --merged der Zweig nicht angegeben ist, sodass der Zweig standardmäßig den aktuellen Zweig und einen Zweig verwendet qualifiziert sich immer als mit sich selbst zusammengeführt (da es keine Unterschiede zwischen einem Zweig und sich selbst gibt!).

Geben Sie also entweder den Zweig an:

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

ODER erster Checkout-Master:

git checkout master | git branch -r --merged | grep -v ...
Kuboon
quelle
18
Beste Antwort bei weitem. Nur eine Anmerkung, mein Hauptzweig heißt, devalso musste ich das ändern
Dorian
41
Ich musste | grep originnachher hinzufügen grep -v master, um zu verhindern, dass Zweige anderer Fernbedienungen zum Ursprung gebracht werden. Es wird git branch -r --merged | grep -v master | grep origin | sed 's/origin\//:/' | xargs -n 1 echo
dringend
9
Ich habe etwas geändert, um auch den developZweig auszuschließen . git branch -r --merged | grep -v master | grep -v develop | sed 's/origin\///' | xargs -n 1 git push --delete origin. Nun stellte sich heraus, dass dies mein Pseudonym war.
Sarat
8
Was dies zur besten Antwort gemacht hat, die ich gelesen habe, ist das -rArgument, das ich nirgendwo anders erwähnt habe. Es ist selbstverständlich, dass nur lokale Niederlassungen eine Haushaltsführung wert sind. Aber auch Fernbedienungen sind voller Müll.
Asbjørn Ulsberg
19
Achtung - gerade erkannt: Hier werden offensichtlich Zweige gefunden, die mit dem aktuellen Zweig zusammengeführt wurden , nicht mit dem Master. Wenn Sie sich also darauf befinden myFeatureBranch, werden diese gelöscht origin/myFeatureBranch. Wahrscheinlich ist es am besten, git checkout masterzuerst.
Jakub.g
190

Nur Adams Antwort ein wenig erweitern:

Fügen Sie dies Ihrer Git-Konfiguration hinzu, indem Sie ausführen git config -e --global

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

Und dann können Sie alle lokalen zusammengeführten Zweige auf einfache Weise löschen git cleanup.

real_ate
quelle
11
sollte der erste Befehl nicht lauten: git branch --merged masterDa Sie sich ansehen möchten, was mit dem Master zusammengeführt wurde, ist der Zweig derzeit nicht ausgecheckt?
Joe Phillips
@ JoePhilllips Einige Leute haben den Hauptzweig nicht Master, sondern developoder oder devund in diesem Fall schlägt der Befehl fehl, fatal: malformed object namees ist besser, einen generischen Befehl zu haben und Sie haben die Verantwortung, ihn auszuführen
smohamed
1
@ JoePhilllips Der Sinn dieser Antwort besteht darin, Adams Antwort (die beste Antwort auf diese Frage) in einem hilfreichen Git-Alias ​​zusammenzufassen. Adams Antwort hat nicht das, was Sie vorschlagen, und so viele Leute haben das nützlich gefunden, dass ich geneigt wäre, meine nicht zu ändern. Ich würde empfehlen, die Diskussion über Adams Antwort zu eröffnen, wenn Sie sich stark dafür fühlen
real_ate
13
Durch Hinzufügen -rzu xargswerden unnötige Fehler ( branch name required) vermieden , wenn dieser Alias ​​mehrmals ausgeführt wird oder wenn kein Zweig mehr gelöscht werden muss. Mein Alias ​​sieht so aus:cleanup = "!git branch --merged | grep -v -P '^\\*|master|develop' | xargs -n1 -r git branch -d"
Verantwortanta
1
Der aktuelle Befehl filtert den Master nicht heraus und entwickelt keine Zweige
Andriy F.
83

Dies funktioniert auch, um alle zusammengeführten Zweige außer dem Master zu löschen.

git branch --merged | grep -v '^* master$' | grep -v '^  master$' | xargs git branch -d
Ismael Abreu
quelle
3
Jetzt wird kein Zweig mehr gelöscht master. Versuchen Sie es grep -v ^master$für die Mitte.
Wchargin
Ich würde auch | grep -v '^\*'vermeiden, den aktuellen Zweig zu löschen, wenn Sie nicht auf master
svassr
5
Das ist großartig, danke! Eine Einschränkung für alle, die dies verwenden: Beachten Sie, dass zwei Leerzeichen vorhanden sind grep -v '^ master$'. Wenn Sie es selbst eingeben und eines verpassen, werden Sie es löschen, masterwenn Sie nicht darauf sind.
Styger
3
@ Mr.Polywhirl Ihre Bearbeitung bricht den Befehl und Sie sollten ihn zurücksetzen. Die beiden Leerzeichen sind erforderlich, da git branchjeder Zweigname in einer neuen Zeile mit zwei Leerzeichen links aufgelistet wird, wenn es sich nicht um den aktuell ausgecheckten Zweig handelt. Sie haben im Wesentlichen garantiert, dass jeder, der diesen Befehl ausführt, seinen Hauptzweig löscht, es sei denn, es handelt sich um den aktuell ausgecheckten Zweig.
Styger
79

Sie möchten die master& develop-Zweige von diesen Befehlen ausschließen.

Lokaler Git klar:

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

Remote Git klar:

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

Synchronisieren Sie die lokale Registrierung von Remote-Zweigen:

git fetch -p
Guido Bouman
quelle
3
+1 auch für die Remote-Version (wird aber weniger benötigt, da wir remote --prune haben). Erwähnenswert ist auch, dass diese Version mit der älteren Git-Version nicht funktioniert
Malko
4
git config --global --add fetch.prune truebeim Abrufen oder Ziehen automatisch beschneiden.
T3rm1
1
Wohlgemerkt, das Beschneiden ist nicht dasselbe wie das Entfernen der Fernbedienung. Das Remote-Löschen löscht tatsächlich die Remote-Zweige, die vollständig mit Ihrem aktuellen Zweig zusammengeführt wurden. Prune bereinigt nur Ihre lokale Registrierung von Remote-Zweigen, die bereits gelöscht wurden.
Guido Bouman
Das Wort vollständig ist etwas irreführend, da ein Zweig als zusammengeführt betrachtet wird, wenn er zuvor zusammengeführt wurde, aber nach dem Zusammenführen neue Commits aufweist, die nicht zusammengeführt wurden.
Scones
Um alle Ursprungsfernbedienungen in einem Aufruf zu löschen, habe ich git branch -r --merged | grep -v '\*\|master\|develop' | grep '^\s*origin/' | sed 's/origin\///' | tr "\n" " " | xargs git push --delete origin
Folgendes
48

Für diejenigen unter Ihnen, die unter Windows arbeiten und PowerShell-Skripte bevorzugen, ist hier eines, das lokale zusammengeführte Zweige löscht:

function Remove-MergedBranches
{
  git branch --merged |
    ForEach-Object { $_.Trim() } |
    Where-Object {$_ -NotMatch "^\*"} |
    Where-Object {-not ( $_ -Like "*master" )} |
    ForEach-Object { git branch -d $_ }
}
Klas Mellbourn
quelle
13
Aus Neugier kann dies aufgit branch --merged | ?{-not ($_ -like "*master")} | %{git branch -d $_.trim()}
Iain Ballard
5
@IainBallard Sicher, ich hätte Aliase verwenden können. Dies wird nicht empfohlen, wenn Sie die Lesbarkeit maximieren möchten. github.com/darkoperator/PSStyleGuide/blob/master/English.md
Klas Mellbourn
1
sicher. Ich fand Ihre Antwort sehr hilfreich :-) Manchmal behindert jedoch die Powershell-Syntax in Langform die Vorgänge in den Blöcken. Aber in erster Linie habe ich etwas vorgeschlagen, das Sie als einmalig kopieren / einfügen oder eingeben könnten. Danke noch einmal.
Iain Ballard
4
Hier ist ein Einzeiler für die Windows-Cmd-Shell, der den Master und Ihren aktuellen Zweig bewahrt: for /f "usebackq" %B in (``git branch --merged^|findstr /v /c:"* " /c:"master"``) do @git branch -d %B(Seufz, ersetzen Sie doppelte Anführungszeichen durch einfache, ich bin nicht sicher, wie ein Literal formatiert werden soll, das Backquotes enthält)
yoyo
42

Ich benutze Adams Antwort seit Jahren. Das heißt, dass es einige Fälle gibt, in denen es sich nicht so verhalten hat, wie ich es erwartet hatte:

  1. Zweige, die das Wort "Master" enthielten, wurden ignoriert, z. B. "Notmaster" oder "Masterful", und nicht nur der Master-Zweig
  2. Zweige, die das Wort "dev" enthielten, wurden ignoriert, z. B. "dev-test", und nicht nur der dev-Zweig
  3. Löschen von Zweigen, die über den HEAD des aktuellen Zweigs erreichbar sind (dh nicht unbedingt Master)
  4. Löschen Sie im getrennten HEAD-Status jeden erreichbaren Zweig aus dem aktuellen Commit

1 & 2 waren einfach zu adressieren, mit nur einer Änderung der Regex. 3 hängt vom gewünschten Kontext ab (dh löscht nur Zweige, die nicht mit dem Master oder mit Ihrem aktuellen Zweig zusammengeführt wurden). 4 kann katastrophal sein (obwohl mit wiederherstellbar git reflog), wenn Sie dies unbeabsichtigt im getrennten HEAD-Zustand ausgeführt haben.

Schließlich wollte ich, dass dies alles in einem Einzeiler ist, für den kein separates Skript (Bash | Ruby | Python) erforderlich ist.

TL; DR

Erstellen Sie einen Git-Alias ​​"Sweep", der ein optionales -fFlag akzeptiert :

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

und rufe es auf mit:

git sweep

oder:

git sweep -f

Die lange, detaillierte Antwort

Für mich war es am einfachsten, ein Beispiel für ein Git-Repo mit einigen Zweigen und Commits zu erstellen, um das richtige Verhalten zu testen:

Erstellen Sie ein neues Git-Repo mit einem einzigen Commit

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

Erstellen Sie einige neue Zweige

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

Gewünschtes Verhalten: Wählen Sie alle zusammengeführten Zweige aus, außer: Master, Entwickeln oder Aktuell

Der ursprüngliche Regex vermisst die Zweige "meisterhaft" und "notmaster":

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

Mit dem aktualisierten regulären Ausdruck (der jetzt "Entwickeln" anstelle von "Entwickeln" ausschließt):

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

Wechseln Sie zu Zweig foo, machen Sie ein neues Commit und checken Sie dann einen neuen Zweig aus, foobar, basierend auf foo:

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

Mein aktueller Zweig ist foobar. Wenn ich den obigen Befehl erneut ausführe, um die zu löschenden Zweige aufzulisten, wird der Zweig "foo" eingeschlossen, obwohl er nicht mit master zusammengeführt wurde:

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

Wenn ich jedoch denselben Befehl auf dem Master ausführe, ist der Zweig "foo" nicht enthalten:

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

Dies liegt einfach daran, dass git branch --mergedstandardmäßig der HEAD des aktuellen Zweigs verwendet wird, sofern nicht anders angegeben. Zumindest für meinen Workflow möchte ich keine lokalen Zweige löschen, es sei denn, sie wurden zum Master zusammengeführt. Daher bevorzuge ich die folgende Variante:

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

Freistehender HEAD-Zustand

Das Verlassen auf das Standardverhalten von git branch --mergedhat noch bedeutendere Konsequenzen im getrennten HEAD-Zustand:

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

Dies hätte den Zweig gelöscht, auf dem ich gerade war, "foobar" zusammen mit "foo", was mit ziemlicher Sicherheit nicht das gewünschte Ergebnis ist. Mit unserem überarbeiteten Befehl jedoch:

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

Eine Zeile, einschließlich des tatsächlichen Löschvorgangs

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

Alles in einem Git-Alias ​​"Sweep" verpackt:

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

Der Alias ​​akzeptiert ein optionales -fFlag. Das Standardverhalten besteht darin, nur Zweige zu löschen, die mit dem Master zusammengeführt wurden. Das -fFlag löscht jedoch Zweige, die mit dem aktuellen Zweig zusammengeführt wurden.

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).
Wirbel
quelle
Warum müssen Sie eine Funktion erstellen? Ist nicht git configatomar?
VasiliNovikov
Um mit dem optionalen '-f'-Argument umzugehen (wenn ich Ihre Frage richtig verstehe)
Wirbel
1
aber wie hilft es? Ich meine den Beginn des Ausdrucks !f(){ git branch .... Es ist eine Funktionsdeklaration, oder? Warum nicht direkt mit anfangen git branch ...?
VasiliNovikov
1
Du hast absolut recht. Meine Antwort wurde entsprechend bearbeitet. Danke für den Zeiger!
Wirbel
Würde das Folgende nicht dasselbe tun wie der Nicht-Kraft-Modus? git checkout master && git branch -d `git branch --merged` && git checkout - Abgesehen davon, dass es gelöscht werden würde develop, aber möglicherweise ein einfacherer Ansatz ist.
Guido Bouman
18

Verwenden von Git Version 2.5.0:

git branch -d `git branch --merged`
drautb
quelle
16
Dies kann masterübrigens den Zweig löschen!
Wazery
4
Wahr. Ich benutze es nur, wenn ich sicher bin, dass ich dran bin master.
Drautb
11
git branch -d $(git branch --merged | grep -v master)
Alexg
1
Dies ist gefährlich, wenn Sie einen Flow haben. Stellen Sie sich vor, Sie haben Master <- Stage <- Dev. Immer noch einfachste Lösung imo
Joseph Briggs
14

Sie können das Commit zur Option --merged hinzufügen. Auf diese Weise können Sie sicherstellen, dass nur Zweige entfernt werden, die mit dem Ursprung / Master zusammengeführt werden

Mit dem folgenden Befehl werden zusammengeführte Zweige von Ihrem Ursprung entfernt.

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

Sie können testen, welche Zweige entfernt werden, indem Sie den Git-Push-Ursprung ersetzen - durch Echo löschen

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo
Jörn Reimerdes
quelle
2
Ich mag die
Testoption
12

Ich verwende das folgende Ruby-Skript, um meine bereits zusammengeführten lokalen und Remote-Zweige zu löschen. Wenn ich es für ein Repository mit mehreren Fernbedienungen mache und nur von einer löschen möchte, füge ich einfach eine select-Anweisung zur Fernbedienungsliste hinzu, um nur die gewünschten Fernbedienungen zu erhalten.

#!/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
mmrobins
quelle
Stört es Sie, wenn ich diesen Leckerbissen für eine kleine Git-Helfer-Bibliothek stehle? github.com/yupiq/git-branch-util
Logan
1
Ich hätte es nicht hierher gebracht, wenn ich mich darum gekümmert hätte, dass Leute den Code auf irgendeine Weise
wiederverwenden
@mmrobins Sie haben ein Extra \/am Anfang der Ablehnungsanweisung für die remote_branchesZeile. Ist das ein Tippfehler oder erfüllt es einen Zweck?
Jawwad
@mmrobins, oh egal, ich sehe die b.split(/\//)Linie jetzt
Jawwad
Wenn Sie dies im Grunde tun möchten, aber über Vanille-Bash statt Ruby: stackoverflow.com/a/37999948/430128
Raman
11

So löschen Sie zusammengeführte Zweige in der PowerShell-Konsole

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

Wenn Sie Master- oder andere Verzweigungsnamen ausschließen möchten , können Sie PowerShell Select-String wie folgt weiterleiten und das Ergebnis an git branch -dfolgende Adresse übergeben :

git branch -d $(git branch --merged | Select-String -NotMatch "master" | %{$_.ToString().Trim()})
Konstantin Tarkus
quelle
1
Höhere Antworten deuten darauf hin, dass der Master oder andere Zweige gefiltert werden. Für diejenigen, die dies in Powershell tun möchten: Git Branch --merged | findstr / v "master" | % {git branch -d $ _. trim ()}
tredzko
@tredzko Guter Punkt. FTR die höhere Antwort ist stackoverflow.com/questions/6127328/… - Sie könnten Ihren Kommentar mit diesem Link erneut veröffentlichen und ich würde dies dann löschen
Ruben Bartelink
es versucht auch zu löschen * master:)
iesen
9

kuboons Antwort hat das Löschen von Zweigen verpasst, deren Zweigname das Wort master enthält. Folgendes verbessert seine Antwort:

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

Natürlich wird der "Master" -Zweig selbst nicht gelöscht :)

Paras
quelle
8

In Git gibt es keinen Befehl, der dies automatisch für Sie erledigt. Sie können jedoch ein Skript schreiben, das Git-Befehle verwendet, um Ihnen das zu geben, was Sie benötigen. Dies kann auf viele Arten erfolgen, je nachdem, welches Verzweigungsmodell Sie verwenden.

Wenn Sie wissen müssen, ob ein Zweig mit dem Master zusammengeführt wurde, gibt der folgende Befehl keine Ausgabe aus, wenn myTopicBranch zusammengeführt wurde (dh Sie können ihn löschen).

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

Sie können den Befehl Git branch verwenden und alle Zweige in Bash analysieren und eine forSchleife über alle Zweige durchführen. In dieser Schleife prüfen Sie mit dem obigen Befehl, ob Sie den Zweig löschen können oder nicht.

ralphtheninja
quelle
7

Hinweis : Ich bin mit früheren Antworten nicht zufrieden (nicht auf allen Systemen, nicht auf Remote-Basis, ohne Angabe des --merged-Zweigs, ohne genaue Filterung). Also füge ich meine eigene Antwort hinzu.

Es gibt zwei Hauptfälle:

Lokal

Sie möchten lokale Zweige löschen , die bereits mit einem anderen lokalen Zweig zusammengeführt wurden . Während des Löschvorgangs möchten Sie einige wichtige Zweige wie Master, Entwicklung usw. beibehalten.

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

Anmerkungen :

  • git branch output --format ".." dient zum Entfernen von Leerzeichen und zum Ermöglichen eines genauen Grep-Abgleichs
  • grep -Ewird anstelle von verwendet egrep , so funktioniert es auch in Systemen ohne egrep (dh: git für Windows).
  • grep -E -v '^master$|^feature/develop$' ist es, lokale Zweige anzugeben, die ich nicht löschen möchte
  • xargs -n 1 git branch -d: Löschen Sie lokale Zweige (bei Remote-Zweigen funktioniert dies nicht).
  • Natürlich wird eine Fehlermeldung angezeigt, wenn Sie versuchen, den aktuell ausgecheckten Zweig zu löschen. Daher schlage ich vor, vorher zum Master zu wechseln.

Fernbedienung

Sie möchten entfernte Zweige löschen , die bereits mit einem anderen entfernten Zweig zusammengeführt wurden . Während des Löschvorgangs möchten Sie einige wichtige Zweige wie HEAD, Master, Releases usw. beibehalten.

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

Anmerkungen :

  • Für Remote verwenden wir die -rOption und geben den vollständigen Filialnamen an :origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release' soll mit den entfernten Zweigen übereinstimmen, die wir nicht löschen möchten.
  • cut -d/ -f2-: Entfernen Sie das nicht benötigte Präfix 'origin /', das sonst vom git branchBefehl ausgedruckt wird .
  • xargs -n 1 git push --delete origin : Löschen Sie entfernte Zweige.
psuzzi
quelle
7

Wenn Sie unter Windows arbeiten, können Sie Windows Powershell oder Powershell 7 mit Out-GridView verwenden , um eine schöne Liste von Zweigen zu erstellen und mit der Maus auszuwählen, welche Sie löschen möchten:

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

Geben Sie hier die Bildbeschreibung ein Nach dem Klicken auf OK übergibt Powershell die Namen dieser Zweige an den git branch -dBefehl und löscht sie Geben Sie hier die Bildbeschreibung ein

Mariusz Pawelski
quelle
6

Sie können das git-del-br Werkzeug verwenden .

git-del-br -a

Sie können es über pipmit installieren

pip install git-del-br

PS: Ich bin der Autor des Tools. Anregungen / Feedback sind willkommen.

tusharmakkar08
quelle
1
@ stackoverflow.com/users/100297/martijn-pieters : Warum wurde diese Antwort gelöscht und abgelehnt?
Tusharmakkar08
1
Ihre Antwort und Ihr Tool funktionieren nicht. Ich verbringe ein paar Stunden damit. Nichts.
SpoiledTechie.com
@ SpoiledTechie.com: Können Sie mir sagen, vor welchem ​​Problem Sie genau stehen? Ich benutze es regelmäßig.
Tusharmakkar08
Ich kann einen Screenshot freigeben, wenn Sie diesen offline schalten möchten. spoiledtechie bei dieser Google Mail-Sache. :)
SpoiledTechie.com
5

Wenn Sie alle lokalen Zweige löschen möchten, die bereits mit dem Zweig zusammengeführt wurden, in dem Sie sich gerade befinden, habe ich auf der Grundlage früherer Antworten einen sicheren Befehl dazu erstellt:

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

Dieser Befehl wirkt sich nicht auf Ihren aktuellen Zweig oder Ihren Hauptzweig aus. Mit dem Flag -t von xargs erfahren Sie auch, was es tut, bevor es es tut.

chrismendis
quelle
5

Ich verwende ein git-flow-ähnliches Namensschema, daher funktioniert dies für mich sehr sicher:

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

Grundsätzlich wird nach zusammengeführten Commits gesucht, die entweder mit string fix/oder beginnen feature/.

Chad M.
quelle
4

Versuchen Sie den folgenden Befehl:

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

Bei Verwendung git rev-parsewird der aktuelle Filialname abgerufen abgerufen, um ihn auszuschließen. Wenn Sie den Fehler erhalten haben, müssen keine lokalen Zweige entfernt werden.

originVersuchen Sie Folgendes, um dasselbe mit Remote-Zweigen zu tun (ändern Sie Ihren Remote-Namen):

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

Falls Sie mehrere Fernbedienungen haben, fügen Sie grep origin |vor , cutum Filter nur das origin.

Wenn der obige Befehl fehlschlägt, versuchen Sie zuerst, die zusammengeführten Remote-Tracking-Zweige zu löschen:

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

Dann git fetchdie Fernbedienung erneut und den vorherigen git push -vdBefehl erneut verwenden.

Wenn Sie es häufig verwenden, sollten Sie es als Aliase in Ihre ~/.gitconfigDatei aufnehmen.

Falls Sie versehentlich einige Zweige entfernt haben, verwenden Sie diese Option, git reflogum die verlorenen Commits zu finden.

Kenorb
quelle
4

Basierend auf einigen dieser Antworten habe ich mein eigenes Bash-Skript erstellt, um es auch zu tun !

Es verwendet git branch --mergedund git branch -dlöscht die zusammengeführten Zweige und fordert Sie vor dem Löschen auf, die einzelnen Zweige einzugeben.

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
}
Earlonrails
quelle
4

Die folgende Abfrage funktioniert für mich

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

Dadurch wird jeder Zweig in der Grep-Pipe gefiltert.

Funktioniert gut über http Klon, aber nicht so gut für die SSH-Verbindung.

user1460965
quelle
4

Stand 2018.07

Fügen Sie dies zu einem [alias]Abschnitt Ihres ~/.gitconfig:

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

Jetzt können Sie einfach anrufen git sweep, um die erforderliche Bereinigung durchzuführen.

Sorin
quelle
Für mich listet der Aufruf von git sweep nur die Zweige auf, die bereinigt werden sollen, aber er entfernt sie nicht
Victor Moraes
4

Unter Windows mit installiertem Git Bash funktioniert egrep -v nicht

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

wo grep -E -vist gleichbedeutend mitegrep -v

Verwenden Sie -dbereits entfernen fusionierte Zweige oder -Dentfernen unmerged Zweige

DevWL
quelle
egrep -v funktioniert bei mir. Ich verwende jedoch Gitbash aus dem Installationsprogramm für gitextensions
Joe Phillips
4

Ich habe die folgende Methode verwendet, um zusammengeführte lokale UND entfernte Zweige in einem cmd zu entfernen .

Ich habe Folgendes in meiner bashrcDatei:

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
}

Originalquelle

Dadurch wird der Hauptzweig nicht gelöscht, sondern zusammengeführte lokale UND Remote-Zweige entfernt . Sobald Sie dies in Ihrer RC-Datei haben, führen rmbSie einfach eine Liste der zusammengeführten Zweige aus, die bereinigt und zur Bestätigung der Aktion aufgefordert werden. Sie können den Code so ändern, dass er nicht ebenfalls um Bestätigung bittet, aber es ist wahrscheinlich gut, ihn beizubehalten.

Prashant
quelle
3

Schreiben Sie ein Skript, in dem Git alle Zweige auscheckt, die zum Master zusammengeführt wurden.

Dann mach es git checkout master.

Löschen Sie abschließend die zusammengeführten Zweige.

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
Komu
quelle
3

Die akzeptierte Lösung ist ziemlich gut, hat aber das einzige Problem, dass auch lokale Zweige gelöscht werden, die noch nicht zu einer Fernbedienung zusammengeführt wurden.

Wenn Sie sich die Ausgabe von ansehen, werden Sie so etwas wie sehen

$ 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)

Zweige blaund issue_248sind lokale Zweige, die stillschweigend gelöscht würden.

Sie können aber auch das Wort sehen [gone], das auf Zweige hinweist, die auf eine Fernbedienung verschoben wurden (die jetzt weg ist), und somit darauf hinweist, dass Zweige gelöscht werden können.

Die ursprüngliche Antwort kann daher in (für kürzere Zeilenlänge in mehrere Zeilen aufgeteilt) geändert werden.

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

zum Schutz der noch nicht zusammengeschlossenen Zweige. Auch das Greifen nach Master, um es zu schützen, ist nicht erforderlich, da dies eine Fernbedienung am Ursprung hat und nicht als weg angezeigt wird.

Heiko Rupp
quelle
3

Für mich werden git branch --mergedkeine Zweige angezeigt, die über GitHub PR zusammengeführt wurden. Ich bin mir der Gründe nicht sicher, aber ich verwende die folgende Zeile, um alle lokalen Zweige zu löschen , die keinen Fernverfolgungszweig haben :

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

Erläuterung:

  • git branch --format "%(refname:short)" gibt eine Liste der lokalen Niederlassungen
  • git branch -r | grep -v HEAD | cut -d/ -f2- Gibt eine Liste der entfernten Zweige an, die herausgefiltert werden HEAD
  • diff <(...) <(...) gibt einen Unterschied in der Ausgabe von zwei Befehlen in Klammern an
  • grep '<' filtert Zweige, die in der ersten Liste vorhanden sind, jedoch nicht in der zweiten
  • cut -c 3- Gibt eine Zeile ab dem 3. Zeichen an, wodurch das Präfix entfernt wird <
  • xargs git branch -Dwird git branch -Dfür jeden Filialnamen ausgeführt

Alternativ können Sie Folgendes vermeiden grep -v '<':

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
Folex
quelle