CLI AI

Alle gemergten lokalen Branches in git löschen

2026-07-02

git branch --merged main | grep -vE '^\*|main|develop' | xargs -r git branch -d löscht jeden lokalen Branch, der bereits in main gemergt ist, außer main und develop. Squash-gemergte Branches rührt der Befehl nicht an: git zeichnet ihre Commits nie als gemergt auf, also bleibt --merged für sie blind — prüfe stattdessen git branch -vv auf die Markierung gone.

1. Erst sehen, was als gemergt gilt

clai
$ clai zeig mir die Branches, die in main gemergt sind→ git branch --merged main  feature-merged* main

Das ist eine reine Leseliste. Der aktuelle Branch ist mit einem Sternchen markiert und kann nicht gelöscht werden — muss er auch nicht.

2. Löschen, aber die Hauptbranches schützen

clai
$ clai lösche lokale Branches, die in main gemergt sind, außer main und develop→ git branch --merged main | grep -vE '^\*|main|develop' | xargs -r git branch -dDeleted branch feature-merged (was fb52fec).

-d ist sicher: git weigert sich, einen Branch mit nicht gemergten Commits zu löschen. Der Filter grep -vE ist notwendig, sonst landet main selbst in der Liste. -r verhindert, dass xargs bei einer leeren Liste überhaupt läuft.

3. Prüfen, dass nichts Wichtiges gelöscht wurde

clai
$ clai zeig mir die verbleibenden Branches→ git branch  feature-open* main

feature-open hat noch nicht gemergte Commits und blieb unangetastet. Das ist die Bestätigung, dass der Filter richtig funktioniert hat.

4. Die Falle: Squash Merge versteckt sich vor --merged

clai
$ clai zeig mir Branches, deren Upstream auf dem Server gelöscht wurde→ git fetch --prune && git branch -vv | grep '\[.*: gone\]'

Das ist der entscheidende Teil. Ein Squash Merge bringt die Commits des Branches nie unverändert in die Historie von main, deshalb zeigt --merged ihn nie an — er bleibt für immer auf deiner Maschine. Aber sein Upstream auf dem Server verschwindet, sobald der Pull Request gemergt wird, und git branch -vv markiert diesen Branch als gone. Das ist das verlässliche Zeichen.

5. Branches mit verschwundenem Upstream löschen

clai
$ clai lösche lokale Branches, deren Quell-Branch auf dem Server gelöscht wurde→ git fetch --prune && git branch --format '%(refname:short) %(upstream:track)' | awk '$2 == "[gone]" {print $1}' | xargs -r git branch -D⚠ CAUTION — this is -D, not -d: it also deletes unmerged branches

-D ist genau deshalb nötig, weil git Squash-gemergte Branches nicht als gemergt betrachtet und sich bei -d weigert. Der Preis dafür: Lies die Liste aus dem vorherigen Befehl, bevor du diesen ausführst.

6. Veraltete Remote-Referenzen aufräumen

clai
$ clai entferne Referenzen auf Branches, die es auf dem Server nicht mehr gibt→ git remote prune origin

Das entfernt nur lokale origin/*-Referenzen — deine Branches bleiben unberührt. Praktisch, wenn die Autovervollständigung ständig Branches vorschlägt, die vor einem halben Jahr geschlossen wurden.

Fallstricke

  • -d und -D haben unterschiedliches Risiko. Klein löscht nur Gemergtes, groß löscht alles. Squash-gemergte Branches brauchen das große D, also erst die Liste, dann löschen.
  • --merged ohne Argument zählt ab dem aktuellen Branch. Auf einem Feature-Branch bekommst du eine völlig andere Liste. Gib die Basis explizit an: --merged main.
  • Ein gelöschter lokaler Branch verschwindet nicht auf dem Server. Dafür braucht es git push origin --delete <name>. Und umgekehrt: Löschen auf dem Server entfernt nicht deine lokale Kopie.

Verwandte Fragen

Wie stelle ich einen versehentlich gelöschten Branch wieder her? git reflog zeigt seinen letzten Commit; dann git branch <name> <hash>. Funktioniert, bis die Garbage Collection läuft.

Warum lässt sich ein Branch nicht löschen? Entweder du stehst gerade auf ihm — wechsle zu main —, oder er hat nicht gemergte Commits und -d schützt dich vor Verlust.

Wie sehe ich, wann ein Branch zuletzt aktualisiert wurde? git branch --sort=-committerdate -v sortiert nach Aktualität — praktisch, um verwaiste Branches zu finden.

Siehe auch

CliAI verwandelt die Formulierungen oben in den exakten Befehl und zeigt ihn, bevor irgendetwas läuft — der -D-Schritt bekommt ein CAUTION-Label statt eines stillen Laufs. In einer Zeile installieren.