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:
- Zweige, die das Wort "Master" enthielten, wurden ignoriert, z. B. "Notmaster" oder "Masterful", und nicht nur der Master-Zweig
- Zweige, die das Wort "dev" enthielten, wurden ignoriert, z. B. "dev-test", und nicht nur der dev-Zweig
- Löschen von Zweigen, die über den HEAD des aktuellen Zweigs erreichbar sind (dh nicht unbedingt Master)
- 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 -f
Flag 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 --merged
standardmäß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 --merged
hat 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 -f
Flag. Das Standardverhalten besteht darin, nur Zweige zu löschen, die mit dem Master zusammengeführt wurden. Das -f
Flag 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).
git branch -D
jeder Zweig gelöscht, unabhängig davon, ob er zusammengeführt wurde oder nicht.