Eliminar las ramas de seguimiento que ya no están en control remoto
¿Existe una forma sencilla de eliminar todas las ramas de seguimiento cuyo equivalente remoto ya no existe?
Ejemplo:
Sucursales (locales y remotas)
- maestro
- origen/maestro
- origen/corrección de errores-a
- origen/corrección de errores-b
- origen/corrección de errores-c
A nivel local, sólo tengo una sucursal maestra. Ahora necesito trabajar en bug-fix-a , así que lo reviso, trabajo en ello y envío los cambios al control remoto. Luego hago lo mismo con bug-fix-b .
Sucursales (locales y remotas)
- maestro
- corrección de errores
- corrección de errores-b
- origen/maestro
- origen/corrección de errores-a
- origen/corrección de errores-b
- origen/corrección de errores-c
Ahora tengo sucursales locales master , bug-fix-a , bug-fix-b . El responsable de la rama Master fusionará mis cambios en la master y eliminará todas las ramas que ya ha fusionado.
Entonces el estado actual es ahora:
Sucursales (locales y remotas)
- maestro
- corrección de errores
- corrección de errores-b
- origen/maestro
- origen/corrección de errores-c
Ahora me gustaría llamar a algún comando para eliminar ramas (en este caso bug-fix-a , bug-fix-b ), que ya no están representadas en el repositorio remoto.
Sería algo parecido al comando existente git remote prune origin
, pero más parecido a git local prune origin
.
git remote prune origin
poda el seguimiento de las ramas que no están en el control remoto.
git branch --merged
enumera las ramas que se han fusionado en la rama actual.
xargs git branch -d
elimina las ramas enumeradas en la entrada estándar.
Tenga cuidado al eliminar las ramas enumeradas por git branch --merged
. La lista podría incluir master
otras ramas que preferirías no eliminar.
Para tener la oportunidad de editar la lista antes de eliminar ramas, puede hacer lo siguiente en una línea:
git branch --merged >/tmp/merged-branches && \
vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches
La forma más segura de hacer esto es usar el comando "plomería" git for-each-ref
con la variable de interpolación %(upstream:track)
, que será [gone]
cuando la rama ya no esté en el remoto:
git fetch -p && for branch in $(git for-each-ref --format '%(refname) %(upstream:track)' refs/heads | awk '$2 == "[gone]" {sub("refs/heads/", "", $1); print $1}'); do git branch -D $branch; done
Este enfoque es algo más seguro que usar el comando "porcelain", porque no hay riesgo de que coincida accidentalmente parte del mensaje de confirmación. Aquí hay una versión que usa los comandos git "porcelana":
git fetch -p && for branch in $(git branch -vv | grep ': gone]' | awk '{print $1}'); do git branch -D $branch; done
La forma en que esto funciona es que después del comando
git fetch -p
elimina las referencias remotas, cuando ejecuta
git branch -vv
mostrará "desaparecido" como estado remoto. Por ejemplo,
$ git branch -vv
master b900de9 [origin/master: behind 4] Fixed bug
release/v3.8 fdd2f4e [origin/release/v3.8: behind 2] Fixed bug
release/v3.9 0d680d0 [origin/release/v3.9: behind 2] Updated comments
bug/1234 57379e4 [origin/bug/1234: gone] Fixed bug
Esto es sobre lo que se repiten los guiones.
La mayoría de estas respuestas en realidad no responden a la pregunta original. Investigué mucho y esta fue la solución más limpia que encontré. Aquí hay una versión un poco más completa de esa respuesta:
- Consulte su sucursal predeterminada. Generalmente
git checkout master
- Correr
git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d
Explicación:
Funciona podando las ramas de seguimiento y luego eliminando las locales que muestran que "desaparecieron" git branch -vv
.
Notas:
Si su idioma está configurado en otro que no sea inglés, deberá cambiar gone
a la palabra adecuada. Las sucursales que sean únicamente locales no serán tocadas. Las ramas que se eliminaron en forma remota pero que no se fusionaron mostrarán una notificación pero no se eliminarán en local. Si desea eliminarlos también cambie -d
a -D
.