Löschen Sie alle lokalen Git-Zweige

320

Ich folge einem Entwicklungsprozess, in dem ich für jedes neue Feature oder jede neue Story-Karte einen neuen lokalen Zweig erstelle. Wenn ich fertig bin, füge ich den Zweig in Master zusammen und drücke dann.

Was im Laufe der Zeit aufgrund einer Kombination aus Faulheit oder Vergesslichkeit passiert, ist, dass ich am Ende eine große Liste lokaler Zweige habe, von denen einige (wie z. B. Spitzen) möglicherweise nicht zusammengeführt wurden.

Ich weiß, wie man alle meine lokalen Zweige auflistet und wie man einen einzelnen Zweig entfernt, aber ich habe mich gefragt, ob es einen git-Befehl gibt, mit dem ich alle meine lokalen Zweige löschen kann.

Unten ist die Ausgabe des git branch --mergedBefehls.

user@machine:~/projects/application[master]$ git branch --merged
  STORY-123-Short-Description
  STORY-456-Another-Description
  STORY-789-Blah-Blah
* master

Alle Versuche, Zweige zu löschen, die mit grep -v \*(gemäß den folgenden Antworten) aufgelistet sind, führen zu Fehlern:

error: branch 'STORY-123-Short-Description' not found.
error: branch 'STORY-456-Another-Description' not found.
error: branch 'STORY-789-Blah-Blah' not found.

Ich benutze:
git 1.7.4.1
ubuntu 10.04
GNU bash, Version 4.1.5 (1) - Release
GNU grep 2.5.4

Louth
quelle
7
Ich bitte Sie, die Antwort von @Andrew zu akzeptieren!
Robert Siemer
Mögliches Duplikat von Wie kann ich alle zusammengeführten Git-Zweige löschen?
Giulio Caccin
@GiulioCaccin Die Frage bezieht sich auch auf Zweige, die möglicherweise nicht zusammengeführt wurden, und ich habe die Frage aktualisiert, um dies explizit widerzuspiegeln.
Louth

Antworten:

383

Der Unterbefehl 'git branch -d' kann mehr als einen Zweig löschen. Vereinfachen Sie also die Antwort von @ sblom, fügen Sie jedoch ein kritisches xargs hinzu:

git branch -D `git branch --merged | grep -v \* | xargs`

oder weiter vereinfacht zu:

git branch --merged | grep -v \* | xargs git branch -D 

Wie von @AndrewC erwähnt, git branchwird davon abgeraten, Skripte zu verwenden . Um dies zu vermeiden, verwenden Sie Folgendes:

git for-each-ref --format '%(refname:short)' refs/heads | grep -v master | xargs git branch -D

Vorsicht beim Löschen geboten!

$ mkdir br
$ cd br; git init
Initialized empty Git repository in /Users/ebg/test/br/.git/
$ touch README; git add README; git commit -m 'First commit'
[master (root-commit) 1d738b5] First commit
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README
$ git branch Story-123-a
$ git branch Story-123-b
$ git branch Story-123-c
$ git branch --merged
  Story-123-a
  Story-123-b
  Story-123-c
* master
$ git branch --merged | grep -v \* | xargs
Story-123-a Story-123-b Story-123-c
$ git branch --merged | grep -v \* | xargs git branch -D
Deleted branch Story-123-a (was 1d738b5).
Deleted branch Story-123-b (was 1d738b5).
Deleted branch Story-123-c (was 1d738b5).
GoZoner
quelle
Dieser Befehl meldet immer noch dieselben Fehler wie in den Kommentaren für die Antwort unten erwähnt. error:branch 'STORY-123-Short-Description' not found.für jede der aufgeführten Niederlassungen.
Louth
1
Funktioniert bei mir; siehe oben mit Details hinzugefügt.
GoZoner
1
Hat die Verwendung von git 1.7.10 Ihr Problem gelöst oder arbeiten Sie lieber direkt im .git-Repository?
GoZoner
1
Wenn Sie eine error:branch 'STORY-123-Short-Description' not found.Fehlermeldung erhalten, liegt dies wahrscheinlich an den Einstellungen für die Git-Farbe. Dies funktionierte für mich (beachten Sie die --no-colorOption):git branch --no-color --merged | grep -v \* | xargs git branch -D
Marcok
3
Die einzige Antwort auf SO habe ich gefunden, dass das funktioniert. Vielen Dank!
Kevin Suttle
140

Ich habe einen schöneren Weg in einem Kommentar zu diesem Thema auf Github gefunden :

git branch --merged master --no-color | grep -v master | grep -v stable | xargs git branch -d

Bearbeiten: Option ohne Farbe hinzugefügt und Ausschluss eines stabilen Zweigs (andere Zweige nach Bedarf in Ihrem Fall hinzufügen)

mBardos
quelle
2
Endlich die Lösung, die ich brauchte
Code Whisperer
1
Ich habe es versucht, aber immer error: branch 'my-branch-name' not found.für jeden Zweig bekommen. Verwenden der Git-Version 1.8.3.4 (Apple Git-47). Irgendeine Idee warum?
Wheresrhys
2
Damit. git for-each-ref --format '%(refname:short)' refs/heads/ | grep -v master | xargs git branch -d
Павел Тявин
1
Gelernte Xargs Verwendung zusammen mit diesem. Vielen Dank
Volem
1
Danke sehr gut.
A. Gusev
105

Das Parsen der Ausgabe von git branchwird nicht empfohlen und ist keine gute Antwort für zukünftige Leser von Stack Overflow.

  1. git branchist ein sogenannter Porzellanbefehl. Porzellanbefehle können nicht maschinell analysiert werden, und die Ausgabe kann sich zwischen verschiedenen Git-Versionen ändern.
  2. Es gibt Benutzerkonfigurationsoptionen, die die Ausgabe so ändern git branch, dass das Parsen schwierig wird (z. B. Kolorierung). Wenn ein Benutzer festgelegt hat, erhalten color.branchSie Steuercodes in der Ausgabe. Dies führt dazu, error: branch 'foo' not found.wenn Sie versuchen, sie in einen anderen Befehl weiterzuleiten. Sie können dies mit dem --no-colorFlag to umgehen git branch, aber wer weiß, welche anderen Benutzerkonfigurationen möglicherweise Probleme verursachen.
  3. git branch kann andere Dinge tun, die beim Parsen ärgerlich sind, z. B. ein Sternchen neben den aktuell ausgecheckten Zweig setzen

Der Betreuer von git hat dies über das Scripting um die git branchAusgabe zu sagen

Um herauszufinden, was der aktuelle Zweig ist, haben gelegentliche / unachtsame Benutzer möglicherweise einen Skript für den Git-Zweig erstellt, was falsch ist. Wir raten aktiv von der Verwendung von Porzellanbefehlen, einschließlich Git-Zweigen, in Skripten ab, da sich die Ausgabe des Befehls ändern kann, um den Anwendungsfall für den menschlichen Verzehr zu erleichtern.

Antworten, die darauf hindeuten, Dateien im .gitVerzeichnis manuell zu bearbeiten (z. B. .git / refs / Heads), sind ähnlich problematisch (Refs befinden sich möglicherweise stattdessen in .git / Packed-Refs, oder Git ändert möglicherweise in Zukunft das interne Layout).

Git bietet den for-each-refBefehl zum Abrufen einer Liste von Zweigen.

Git 2.7.X führt die --mergedOption ein, damit Sie wie folgt vorgehen können , um alle zusammengeführten Zweige zu finden und zu löschenHEAD

for mergedBranch in $(git for-each-ref --format '%(refname:short)' --merged HEAD refs/heads/)
do
    git branch -d ${mergedBranch}
done

Ab Git 2.6.X müssen Sie alle lokalen Zweige auflisten und sie dann einzeln testen, um festzustellen, ob sie zusammengeführt wurden (was erheblich langsamer und etwas komplizierter ist).

for branch in $(git for-each-ref --format '%(refname:short)' refs/heads/)
do
    git merge-base --is-ancestor ${branch} HEAD && git branch -d ${branch}
done
Andrew C.
quelle
git branch --no-color 2>/dev/null?
Nobar
5
Es ist sicher eine Verbesserung. Sie werden immer das Problem haben, das * herauszufiltern, und es macht amüsante Dinge, wenn jemand es von einem abgetrennten Kopf aus laufen lässt. Das Hauptproblem ist git branchjedoch ein Porzellanbefehl, und es gibt keine Garantie dafür, dass sich die Ausgabe in einer zukünftigen Version von git nicht ändert.
Andrew C
Vielen Dank an @AndrewC - dies beantwortet sowohl die Frage nach den mysteriösen Fehlern "Zweig nicht gefunden" als auch eine funktionierende Lösung mit einem geeigneteren Befehl! 👍
Jason
2
Wie werden GIT-Befehle für "Porzellan" und "Nicht-Porzellan" identifiziert?
GoZoner
1
Wäre wahrscheinlich eine nützliche Erweiterung, um 'dev' und 'master' standardmäßig auszuschließen?
PandaWood
65

Der einfachere Weg, alle Zweige zu löschen, aber andere wie "Entwickeln" und "Master" beizubehalten, ist der folgende:

git branch | grep -v "develop" | grep -v "master" | xargs git branch -D

sehr hilfreich !

Geoom
quelle
8
Sie haben einen uralten Thread wiederbelebt und eine praktisch identische Antwort auf einen vorhandenen Thread veröffentlicht, der fehlerhaft ist und die Sicherheitsänderungen, die er hatte, fehlt. Dies ist keine gute Antwort.
Andrew C
5
Diese Antwort wird deutlich, wenn die Ausgabe vom Git-Zweig weitergeleitet, geändert und an den Git-Zweig -D übergeben wird. Keine Notwendigkeit, gemein zu sein.
Pam
Diese Lösung hat bei mir funktioniert. Alle lokalen Filialen gelöscht.
Prad
1
Dadurch wird kein Zweig gelöscht, der das Wort "Entwickeln" oder "Master" wie "Develop_Feature" oder "Master_Feature" enthält.
Django
Dies ist die Antwort, nach der ich gesucht habe Kon
Konrad G
60

So löschen Sie jeden Zweig außer dem, den Sie gerade ausgecheckt haben:

for b in `git branch --merged | grep -v \*`; do git branch -D $b; done

Ich würde empfehlen git branch -D $b, echo $bdie ersten Male zu wechseln , um sicherzustellen, dass die von Ihnen beabsichtigten Zweige gelöscht werden.

sblom
quelle
1
Mit diesem Befehl error:branch 'a_branch_name' not found.kann ich sehen, was Sie versuchen, und ich habe mit dem Befehl herumgespielt, aber aus irgendeinem Grund scheint Git die angegebenen Zweignamen nicht zu mögen ...
Louth
Hmmm. git branch --merged
Um die
Meine Filialnamen haben das FormatSTORY-123-Short-Description
Louth
und wenn du rennst git branch --merged, bekommst du eine Liste mit einer davon in jeder Zeile?
sblom
1
sagt es wörtlich error:branch 'a_branch_name' not found.? Oder beschwert es sich über einen der Zweignamen aus Ihrer git branchobigen Ausgabe?
sblom
52

Mit dem folgenden Befehl werden alle lokalen Zweige außer dem Hauptzweig gelöscht.

git branch | grep -v "master" | xargs git branch -D

Der obige Befehl

  1. Listen Sie alle Zweige auf
  2. Ignorieren Sie aus der Liste den Hauptzweig und nehmen Sie den Rest der Zweige
  3. Löschen Sie den Zweig
Jäger
quelle
4
Ich würde git branch | grep -v "master" | xargs git branch -dzuerst verwenden, damit ich nicht zusammengeführte Zweige lösche, nur um sicher zu gehen. Aber schöne Antwort!
Jonas Lomholdt
3
Hier ist eine Powershell-Version,@(git branch | Select-String -Pattern "[^(*?)\s? master]") | ForEach-Object{$_.Line.Trim()} | %{git branch -D $_}
Jonas Lomholdt
1
@baklazan Dies würde nur in der Windows 10-Befehlszeile funktionieren, wenn Sie einige Tools installiert haben. Sie haben wahrscheinlich MINGW oder ähnliches und Sie wissen es nicht.
KthProg
42

Nur eine Anmerkung, ich würde auf Git 1.7.10 upgraden. Möglicherweise erhalten Sie hier Antworten, die für Ihre Version nicht funktionieren. Ich vermute, dass Sie dem Filialnamen ein Präfix voranstellen müssten refs/heads/.

VORSICHT Fahren Sie nur dann mit den folgenden Schritten fort, wenn Sie eine Kopie Ihres Arbeitsordners und Ihres .git-Verzeichnisses erstellt haben.

Manchmal lösche ich einfach die Zweige, aus denen ich nicht direkt möchte .git/refs/heads. Alle diese Zweige sind Textdateien, die die 40 Zeichen sha-1 des Commits enthalten, auf das sie verweisen. Sie haben irrelevante Informationen in Ihrem, .git/configwenn Sie für eines von ihnen ein spezifisches Tracking eingerichtet haben. Sie können diese Einträge auch manuell löschen.

Adam Dymitruk
quelle
Endlich eine einfache und pragmatische Option. Ich mag es: D
Melvyn
2
Dies funktioniert nicht, wenn Sie Refs gepackt haben oder wenn Sie manchmal von einem Remote-Server geklont haben (wodurch Sie gepackte Dateien erhalten). Wenn Sie Refs gepackt haben, werden die Refs nicht in .git / refs / Heads gespeichert, sondern in einer Datei namens "Packed-Refs". Siehe git-scm.com/docs/git-pack-refs .
Alexander Bird
1
Es scheint eine schlechte Idee zu sein, den Zweig zu entfernen, den Sie gerade ausgecheckt haben
Moberg
@Moberg Checke einfach vorher ein Commit aus und dein losgelöster HEAD schwebt in Ordnung.
RomainValeri
33

Versuchen Sie den folgenden Shell-Befehl:

git branch | grep -v "master" | xargs git branch -D

Erläuterung:

  • 🛒 Holen Sie sich alle Zweige per git branch | grep -v "master"Befehl
  • 👇 Wählen Sie jeden Zweig mit xargsBefehl aus
  • 💦 Zweig löschen mit xargs git branch -D
Pravin
quelle
3
Obwohl dies eine richtige Antwort sein kann. Eine Codezeile ist nicht sehr nützlich, ohne zu erklären, was und wie sie die ursprüngliche Frage löst. Bitte geben Sie Details zu Ihrer Antwort an.
RyanNerd
28

So löschen Sie alle lokalen Zweige unter Linux außer dem, auf dem Sie sich befinden

// hard delete

git branch -D $(git branch)
Ashish Yadav
quelle
2
Dieser fühlt sich sicherer an, als in .git zu gehen und Sachen zu entfernen.
Nelsontruran
25

Ich fand es einfacher, nur Texteditor und Shell zu verwenden.

  1. Geben Sie die git checkout <TAB>Shell ein. Zeigt alle lokalen Niederlassungen an.
  2. Kopieren Sie sie in einen Texteditor und entfernen Sie diejenigen, die Sie behalten müssen.
  3. Ersetzen Sie Zeilenumbrüche durch Leerzeichen. (In SublimeText ist es super einfach.)
  4. Shell öffnen, Typ git branch -D <PASTE THE BRANCHES NAMES HERE>.

Das ist es.

culebrón
quelle
Ich glaube nicht, dass Sie den Zweig entfernen können, auf dem Sie stehen.
Dong Thang
@Dong Neben diesem Zweig befindet sich ein *, sodass Sie ihn einfach aus der kopierten Liste entfernen können!
Melanie
12

Ich hatte eine ähnliche Situation und fand kürzlich den folgenden Befehl nützlich.

git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep>/) printf "%s", $0 }'`

Wenn Sie mehrere Zweige behalten möchten, dann

git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep1>|<Branch_You_Want_to_Keep2>/) printf "%s", $0 }'`

hoffe das hilft jemandem.

4u.Ans
quelle
1
Schön, aber ich brauchte Backticks, um es zum Laufen zu bringen. git branch -D `git branch | awk '{ if ($0 !~ /master/) printf "%s", $0 }'` Eigentlich glaube ich, dass Sie sie ursprünglich hatten, aber sie gingen in der SO-Formatierung verloren.
Tassinari
10

Löschen Sie in der Windows-Befehlszeile alle außer dem aktuell ausgecheckten Zweig mit:

for /f "tokens=*" %f in ('git branch ^| find /v "*"') do git branch -D %f
kiewic
quelle
7

Wenn Sie Git selbst nicht durchlaufen müssen, können Sie Köpfe auch manuell oder programmgesteuert unter .git / refs / head löschen . Folgendes sollte mit minimalen Optimierungen unter Bash funktionieren:

shopt -s extglob
rm -rf .git/refs/heads/!(master)

Dadurch wird jeder lokale Zweig außer Ihrem Hauptzweig gelöscht. Da Ihre Upstream-Filialen unter .git / refs / remotes gespeichert sind , bleiben sie unberührt.

Wenn Sie Bash nicht verwenden oder viele Git-Repositorys gleichzeitig rekursieren möchten, können Sie mit GNU find etwas Ähnliches tun:

find . \
    -path remotes -path logs -prune -o \
    -wholename \*.git/refs/heads/\* \! -name master -print0 |
xargs -0 rm -rf

Die Suchlösung ist wahrscheinlich portabler, aber das Bereinigen von Pfaden und Dateinamen ist schwierig und möglicherweise fehleranfälliger.

Todd A. Jacobs
quelle
Cool. Visuelles Löschen :)
Sandalone
5

Keine der Antworten hat meine Bedürfnisse voll erfüllt, also los geht's:

git branch --merged | grep -E "(feature|bugfix|hotfix)/" | xargs git branch -D && git remote prune origin

Dadurch werden alle Ortsvereine löschen , die zusammengeführt werden und beginnend mit feature/, bugfix/oder hotfix/. Anschließend wird die Upstream-Fernbedienung originbeschnitten (möglicherweise müssen Sie ein Kennwort eingeben).

Funktioniert auf Git 1.9.5.

user4401817
quelle
5

Basierend auf einer Kombination mehrerer Antworten hier - Wenn Sie alle Zweige, die auf der Fernbedienung vorhanden sind , behalten, aber den Rest löschen möchten, reicht der folgende Oneliner aus:

git for-each-ref --format '%(refname:short)' refs/heads | grep -Ev `git ls-remote --quiet --heads origin | awk '{print substr($2, 12)}'| paste -sd "|" -` | xargs git branch -D
Srishan Bhattarai
quelle
3

Obwohl dies keine Befehlszeilenlösung ist, bin ich überrascht, dass die Git-GUI noch nicht vorgeschlagen wurde.

Ich benutze die Befehlszeile 99% der Zeit, aber in diesem Fall ist sie entweder viel zu langsam (daher die ursprüngliche Frage), oder Sie wissen nicht, was Sie löschen werden, wenn Sie auf eine langwierige, aber clevere Shell-Manipulation zurückgreifen.

Die Benutzeroberfläche löst dieses Problem, da Sie die zu entfernenden Zweige schnell abhaken und an die Zweige erinnert werden können, die Sie behalten möchten, ohne für jeden Zweig einen Befehl eingeben zu müssen.

Gehen Sie auf der Benutzeroberfläche zu Zweig -> Löschen und Strg + Klicken Sie auf die Zweige, die Sie löschen möchten, damit sie hervorgehoben werden. Wenn Sie sicher sein möchten, dass sie zu einem Zweig zusammengeführt werden (z. B. dev), klicken Sie unter Nur löschen, wenn Zusammengeführt, um den lokalen Zweig auf zu setzen dev. Andernfalls setzen Sie es auf Immer , um diese Prüfung zu ignorieren.

GitUI: Lokale Zweige löschen

Däne Bouchie
quelle
1

Für Powershell funktioniert dies:

git branch --format '%(refname:lstrip=2)' --merged `
    | Where-Object { $_ -ne 'master' } `
    | ForEach-Object { git branch -d $_ }
Lucas
quelle
0

Das folgende Skript löscht Zweige. Verwenden Sie es und ändern Sie es auf eigenes Risiko usw. usw.

Basierend auf den anderen Antworten in dieser Frage habe ich mir ein schnelles Bash-Skript geschrieben. Ich habe es "gitbd" (git branch -D) genannt, aber wenn Sie es verwenden, können Sie es nach Belieben umbenennen.

gitbd() {
if [ $# -le 1 ]
  then
    local branches_to_delete=`git for-each-ref --format '%(refname:short)' refs/heads/ | grep "$1"`
    printf "Matching branches:\n\n$branches_to_delete\n\nDelete? [Y/n] "
    read -n 1 -r # Immediately continue after getting 1 keypress
    echo # Move to a new line
    if [[ ! $REPLY == 'N' && ! $REPLY == 'n' ]]
      then
        echo $branches_to_delete | xargs git branch -D
    fi
else
  echo "This command takes one arg (match pattern) or no args (match all)"
fi
}

Es wird angeboten, alle Zweige zu löschen, die mit einem Musterargument übereinstimmen, wenn sie übergeben werden, oder alle lokalen Zweige, wenn sie ohne Argumente aufgerufen werden. Es gibt Ihnen auch einen Bestätigungsschritt, da wir Dinge löschen, also ist das schön.

Es ist irgendwie dumm - wenn es keine Zweige gibt, die dem Muster entsprechen, merkt es es nicht.

Ein Beispiel für einen Ausgabelauf:

$ gitbd test
Matching branches:

dummy+test1
dummy+test2
dummy+test3

Delete? [Y/n] 
Dherman
quelle
0

Ich habe ein Shell-Skript geschrieben, um alle lokalen Zweige außer zu entfernen develop

branches=$(git branch | tr -d " *")
output=""
for branch in $branches 
do
  if [[ $branch != "develop" ]]; then
    output="$output $branch"
  fi
done
git branch -d $output
nhp
quelle
0

Die obigen Antworten funktionieren einwandfrei. Hier ist ein anderer Ansatz, wenn wir viele Zweige im lokalen Repo haben und viele Zweige löschen müssen, außer wenige, die auf dem lokalen Computer liegen.

Zuerst git branchwerden alle lokalen Niederlassungen aufgelistet.

So transponieren Sie die Spalte mit den Verzweigungsnamen in eine einzelne Zeile in der Datei, indem Sie einen Unix-Befehl ausführen .
git branch > sample.txt
Dadurch wird sie in der Datei sample.txt gespeichert. Führen Sie den
awk 'BEGIN { ORS = " " } { print }' sample.txt
Befehl in der Shell aus. Dadurch wird die Spalte in eine Zeile umgewandelt und die Liste der Zweignamen in eine einzelne Zeile kopiert.

Und dann renn
git branch -D branch_name(s).
Dadurch werden alle aufgelisteten Zweige gelöscht, die in local vorhanden sind

Deepak G.
quelle
0

Der pragmatischste Weg: masterStellen Sie sicher, dass Sie keine nicht festgeschriebene Arbeit haben, legen Sie bei Bedarf fest / pushen Sie, klonen Sie eine neue Kopie des Repositorys und löschen Sie die alte.

Patrick Sanan
quelle
0

Zu diesem Zweck können Sie Git-Extras verwenden

$ git delete-merged-branches
Deleted feature/themes (was c029ab3).
Deleted feature/live_preview (was a81b002).
Deleted feature/dashboard (was 923befa).
Andriy Orehov
quelle
0

Ich habe kein Grep oder anderes Unix auf meiner Box, aber dies funktionierte vom VSCode-Terminal aus:

git branch -d $(git branch).trim()

Ich verwende das Kleinbuchstaben d, damit nicht zusammengeführte Zweige nicht gelöscht werden.

Ich war auch auf Master, als ich es tat, * masterexistiert also nicht, also hat es nicht versucht, Master zu löschen.

Ron Newcomb
quelle
Bestätigt: Wenn nicht masteraktiviert, wird dieser Befehl gelöscht master.
Brett Rowberry
-1

Stellen Sie sicher, dass Sie dies zuerst tun

git fetch

Wenn Sie alle Informationen zu Remote-Zweigen haben, entfernen Sie mit dem folgenden Befehl jeden einzelnen Zweig außer Master

 git branch -a | grep -v "master" | grep remotes | sed 's/remotes\/origin\///g' | xargs git push origin --delete
Meng
quelle