git branch --merged main | grep -vE '^\*|main|develop' | xargs -r git branch -d elimina todas las ramas locales ya fusionadas en main, excepto main y develop. No tocará las ramas fusionadas con squash: git nunca registra sus commits como fusionados, así que --merged nunca las ve — para esas, revisa git branch -vv y busca la marca gone.
1. Primero mira qué se considera fusionado
$ clai muestra las ramas fusionadas en main→ git branch --merged main feature-merged* main
Es una lista de solo lectura. La rama actual está marcada con un asterisco y no se puede eliminar — ni hace falta.
2. Elimínalas, pero protege las ramas principales
$ clai elimina las ramas locales fusionadas en main, excepto main y develop→ git branch --merged main | grep -vE '^\*|main|develop' | xargs -r git branch -dDeleted branch feature-merged (was fb52fec).
-d es seguro: git se niega a eliminar una rama con commits sin fusionar. El filtro grep -vE es obligatorio, o main termina en la lista. -r evita que xargs se ejecute cuando la lista está vacía.
3. Confirma que no se borró nada importante
$ clai muestra las ramas restantes→ git branch feature-open* main
feature-open todavía tiene commits sin fusionar y se quedó donde estaba. Esa es la comprobación de que el filtro funcionó bien.
4. La trampa: el squash merge se esconde de --merged
$ clai muestra las ramas cuyo upstream se eliminó en el servidor→ git fetch --prune && git branch -vv | grep '\[.*: gone\]'
Esta es la parte que importa. Un squash merge nunca lleva los commits de la rama al historial de main tal cual, así que --merged nunca la mostrará — se queda en tu máquina para siempre. Pero su upstream en el servidor desaparece en cuanto se fusiona el pull request, y git branch -vv marca esa rama como gone. Esa es la señal fiable.
5. Elimina las ramas con upstream desaparecido
$ clai elimina las ramas locales cuya rama de origen se eliminó en el servidor→ 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 es necesario justamente porque git no considera fusionadas las ramas con squash merge, y se niega con -d. El precio: lee la lista del comando anterior antes de ejecutar este.
6. Limpia las referencias obsoletas del servidor
$ clai elimina las referencias a ramas que ya no existen en el servidor→ git remote prune origin
Esto solo elimina referencias locales origin/* — no toca tus ramas. Útil cuando el autocompletado sigue sugiriendo ramas cerradas hace seis meses.
Trampas habituales
-dy-Dtienen niveles de riesgo distintos. La minúscula solo elimina lo fusionado, la mayúscula elimina cualquier cosa. Las ramas con squash necesitan mayúscula, así que primero lista, luego elimina.--mergedsin argumento cuenta desde la rama actual. Parado en una rama feature obtienes una lista completamente distinta. Indica la base explícitamente:--merged main.- Eliminar una rama local no la elimina en el servidor. Para eso hace falta
git push origin --delete <nombre>. Y al revés: eliminarla en el servidor no borra tu copia local.
Preguntas relacionadas
¿Cómo recupero una rama que borré por accidente? git reflog muestra su último commit; luego git branch <nombre> <hash>. Funciona hasta que corre la recolección de basura.
¿Por qué una rama no se elimina? O estás parado en ella — cambia a main — o tiene commits sin fusionar y -d te está protegiendo de perderlos.
¿Cómo veo cuándo se actualizó una rama por última vez? git branch --sort=-committerdate -v ordena por antigüedad — útil para encontrar las abandonadas.
Ver también
- Deshacer el último commit de git sin perder los cambios
- Elimina un secreto del historial de git
- Tareas de git dichas en voz alta
CliAI convierte las frases de arriba en el comando exacto y lo muestra antes de ejecutar nada — el paso con -D recibe una etiqueta CAUTION, no una ejecución silenciosa. Instálalo en una línea.