git - tag - Cómo podar las ramas de seguimiento locales que ya no existen en el control remoto
para que sirven las ramas git (24)
Solución de Windows
Para Microsoft Windows Powershell:
git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Split(" ")[0]} | % {git branch -d $_}
Explicacion
git checkout master
cambia a la rama maestra
git remote update origin --prune
las ramas remotas
git branch -vv
obtiene una salida detallada de todas las ramas ( referencia de git )
Select-String -Pattern ": gone]"
obtiene solo los registros donde se han eliminado del control remoto.
% { $_.toString().Split(" ")[0]}
obtiene el nombre de la rama
% {git branch -d $_}
borra la rama
Con git remote prune origin
puedo eliminar las sucursales locales que ya no están en el control remoto.
Pero también quiero eliminar las sucursales locales que se crearon a partir de esas sucursales remotas (un chequeo si no están fusionadas sería bueno).
¿Cómo puedo hacer esto?
¿Utilizando la GUI? Procedimiento manual, pero rápido y fácil.
$ git gui
Seleccione "Rama -> Eliminar". Puede seleccionar varias ramas con ctrl-clic (ventanas) y eliminarlas todas.
Basándome en las respuestas anteriores, estoy usando una línea más corta:
git remote prune origin | grep pruned | awk ''BEGIN{FS="/"} ; { print $2 }'' | xargs git branch -d
Basado en las respuestas anteriores, vine con esta solución de una línea:
git remote prune origin; git branch -r | awk ''{print $1}'' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk ''{print $1}'' | xargs git branch -d
Después de la poda, puede obtener la lista de sucursales remotas con git branch -r
. La lista de sucursales con su sucursal de seguimiento remoto se puede recuperar con git branch -vv
. Entonces, al usar estas dos listas puede encontrar las ramas de seguimiento remoto que no están en la lista de remotos.
Esta línea debería hacer el truco (requiere bash
o zsh
, no funcionará con el shell Bourne estándar):
git branch -r | awk ''{print $1}'' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk ''{print $1}'' | xargs git branch -d
Esta cadena obtiene la lista de ramas remotas y la pasa a egrep
través de la entrada estándar. Y filtra las sucursales que tienen una sucursal de seguimiento remoto (usando git branch -vv
y filtrando las que tienen origin
) para obtener la primera columna de esa salida, que será el nombre de la sucursal. Finalmente pasando todos los nombres de rama al comando eliminar rama.
Como utiliza la opción -d
, no eliminará las ramas que no se hayan fusionado en la rama en la que se encuentra cuando ejecuta este comando.
También recuerda que deberás ejecutar git fetch --prune
primero , de lo contrario, git branch -r
seguirá viendo las sucursales remotas.
Eliminar cualquier rama que no esté actualizada con el maestro
git co master && git branch | sed s//*// / | xargs git branch -d 2> /dev/null
En medio de la información presentada por git help fetch
, hay un pequeño artículo:
-p, --prune
After fetching, remove any remote-tracking branches which no longer exist on the remote.
Entonces, tal vez, git fetch -p
es lo que estás buscando?
EDIT: Ok, para aquellos que aún debaten esta respuesta 3 años después del hecho, aquí hay un poco más de información sobre por qué presenté esta respuesta ...
Primero, el OP dice que quieren "eliminar también las sucursales locales que se crearon desde esas sucursales remotas [que ya no están en el remoto]". Esto no es inequívocamente posible en git
. Aquí hay un ejemplo.
Digamos que tengo un repositorio en un servidor central, y tiene dos sucursales, llamadas A
y B
Si clono ese repositorio en mi sistema local, mi clon tendrá referencias locales (aún no sucursales reales) llamadas origin/A
y origin/B
Ahora digamos que hago lo siguiente:
git checkout -b A origin/A
git checkout -b Z origin/B
git checkout -b C <some hash>
Los hechos pertinentes aquí son que, por algún motivo, elegí crear una sucursal en mi repositorio local que tenga un nombre diferente al de su origen, y también tengo una sucursal local que aún no existe en el repositorio de origen.
Ahora digamos que elimino las ramas A
y B
en el repositorio remoto y actualizo mi repositorio local ( git fetch
de alguna forma), lo que hace que mis referencias locales origin/A
y origin/B
desaparezcan. Ahora, mi repositorio local tiene tres sucursales aún, A
, Z
y C
Ninguno de estos tiene una rama correspondiente en el repositorio remoto. Dos de ellos fueron "creados a partir de ... sucursales remotas", pero incluso si sé que solía haber una sucursal llamada B
en el origen, no tengo forma de saber que Z
se creó a partir de B
, porque se le cambió el nombre en El proceso, probablemente por una buena razón. Entonces, realmente, sin un proceso externo que registre metadatos de origen de rama, o un ser humano que conozca la historia, es imposible determinar cuál de las tres ramas, si las hay, apunta al OP para su eliminación. Sin alguna información externa que git
no mantiene automáticamente para usted, git fetch -p
es lo más cercano que puede obtener, y cualquier método automático para intentar literalmente lo que el OP pidió corre el riesgo de eliminar demasiadas sucursales, o perder algunas que el OP de lo contrario querría borrado.
También hay otros escenarios, por ejemplo, si creo tres ramas separadas del origin/A
para probar tres enfoques diferentes de algo, y luego el origin/A
desaparece. Ahora tengo tres ramas, que obviamente no todas coinciden con el nombre, pero fueron creadas desde el origin/A
, por lo que una interpretación literal de la pregunta de OP requeriría eliminar las tres. Sin embargo, eso puede no ser deseable, si incluso pudieras encontrar una manera confiable de hacerlos coincidir ...
Enumera las sucursales locales cuya rama de seguimiento remoto se elimina de la remota
$ git remote prune origin --dry-run
Si desea quitar la referencia a estas sucursales locales de las locales que no están rastreadas
$ git remote prune origin
Esto eliminará las sucursales locales para las que se han eliminado las sucursales de seguimiento remoto. (Asegúrate de que estás en la rama master
!)
git checkout master
git branch -vv | grep '': gone]'' | awk ''{print $1}'' | xargs git branch -d
Detalles:
git branch -vv
muestra "ido" para las sucursales locales a las que se hagit branch -vv
el control remoto.mybranch abc1234 [origin/mybranch: gone] commit comments
-d
comprobará si se ha fusionado (-D
lo eliminará independientemente)error: The branch ''mybranch'' is not fully merged.
Estoy bastante seguro de que git remote prune origin
es lo que quieres.
Puede ejecutarlo como git remote prune origin --dry-run
para ver qué haría sin hacer cambios.
Hay un buen paquete NPM que lo hace por usted (y debería funcionar en varias plataformas).
npm install -g git-removed-branches
con: npm install -g git-removed-branches
Y luego git removed-branches
le mostrará todas las ramas locales obsoletas, y git removed-branches --prune
para eliminarlas realmente.
He convertido la respuesta aceptada en un script robusto. Lo encontrarás en mi repositorio de git-extensions .
$ git-prune --help
Remove old local branches that do not exist in <remote> any more.
With --test, only print which local branches would be deleted.
Usage: git-prune [-t|--test|-f|--force] <remote>
Intente esto en git bash, para buscar y eliminar las referencias a las sucursales eliminadas, y luego pode las sucursales locales que estaban siguiendo las eliminadas:
git fetch -p && git branch -d `git branch -vv | grep '': gone]'' | awk ''{print $1}'' | xargs`
Recuerde registrar primero una rama que no se eliminará, de modo que no bloquee la eliminación de la rama.
La siguiente es una adaptación de la respuesta de @ wisbucky para usuarios de Windows:
for /f "tokens=1" %i in (''git branch -vv ^| findstr ": gone]"'') DO git branch %i -d
Uso posh-git y desafortunadamente a PS no le gusta el desnudo, así que creé un script de comando simple llamado PruneOrphanBranches.cmd:
@ECHO OFF
for /f "tokens=1" %%i in (''git branch -vv ^| findstr ": gone]"'') DO CALL :ProcessBranch %%i %1
GOTO :EOF
:ProcessBranch
IF /I "%2%"=="-d" (
git branch %1 %2
) ELSE (
CALL :OutputMessage %1
)
GOTO :EOF
:OutputMessage
ECHO Will delete branch [%1]
GOTO :EOF
:EOF
Llámelo sin parámetros para ver una lista, y luego llámelo con "-d" para realizar la eliminación real o "-D" para cualquier rama que no esté completamente fusionada pero que quiera eliminar de todos modos.
La variante de Schleis no me funciona (Ubuntu 12.04), así que permítame proponer mis variantes (claras y brillantes :):
Variante 1 (preferiría esta opción):
git for-each-ref --format=''%(refname:short) %(upstream)'' refs/heads/ | awk ''$2 !~/^refs//remotes/'' | xargs git branch -D
Variante 2:
a. Funcionamiento en seco
comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F ''/'' ''{print $2}'' | sort ) | awk ''{print "git branch -D " $1}''
segundo. Quitar ramas
comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F ''/'' ''{print $2}'' | sort ) | xargs git branch -D
La versión Powershell de la git branch --merged master | grep -v ''^[ *]*master$'' | xargs git branch -d
git branch --merged master | grep -v ''^[ *]*master$'' | xargs git branch -d
git branch --merged master | %{ if($_ -notmatch ''/*.*master''){ git branch -d "$($_.Trim())" }}
Esto eliminará cualquier rama local que se haya fusionado en el maestro, mientras esté en la rama maestra .
git checkout master
para cambiar.
Puedes usar este comando:
git branch --merged master | grep -v "/* master" | xargs -n 1 git branch -d
Git Clean: elimina las ramas ya fusionadas, incluido el desglose del comando
Quería algo que eliminara todas las sucursales locales que estaban rastreando una sucursal remota, en el origin
, donde la sucursal remota se ha eliminado ( gone
). No quería eliminar las sucursales locales que nunca se configuraron para rastrear una sucursal remota (es decir, mis sucursales de desarrollo local). Además, quería un sencillo de una sola línea que solo use git
u otras herramientas CLI simples, en lugar de escribir scripts personalizados. Terminé usando un poco de grep
y awk
para hacer este comando simple, luego lo agregué como un alias en mi ~/.gitconfig
.
[alias]
prune-branches = !git remote prune origin && git branch -vv | grep '': gone]'' | awk ''{print $1}'' | xargs -r git branch -D
Aquí hay un comando git config --global ...
para agregarlo fácilmente como git prune-branches
:
git config --global alias.prune-branches ''!git remote prune origin && git branch -vv | grep ''"''"'': gone]''"''"'' | awk ''"''"''{print $1}''"''"'' | xargs -r git branch -d''
NOTA: El uso de la bandera -D
para git branch
puede ser muy peligroso. Por lo tanto, en el comando de configuración anterior uso la opción -d
para git branch
lugar de -D
; Yo uso -D
en mi configuración real. Uso -D
porque no quiero escuchar a Git quejarse de las ramas no unidas, solo quiero que se vayan. Es posible que desee esta funcionalidad también. Si es así, simplemente use -D
lugar de -d
al final de ese comando de configuración.
Si desea eliminar todas las sucursales locales que ya están fusionadas en el maestro, puede usar el siguiente comando:
git branch --merged master | grep -v ''^[ *]*master$'' | xargs git branch -d
Si usa Windows y Powershell, puede usar lo siguiente para eliminar todas las sucursales locales que se han fusionado en la sucursal que está actualmente seleccionada:
git branch --merged | ? {$_[0] -ne ''*''} | % {$_.trim()} | % {git branch -d $_}
Explicación
- Enumera la rama actual y las ramas que se han fusionado en ella
- Filtra la rama actual
- Limpia los espacios iniciales o finales de la salida de
git
para cada nombre de rama restante - Borra las sucursales locales fusionadas
Vale la pena ejecutar git branch --merged
primero se git branch --merged
por sí solo para asegurarse de que solo eliminará lo que usted espera.
(Portado / automatizado desde http://railsware.com/blog/2014/08/11/git-housekeeping-tutorial-clean-up-outdated-branches-in-local-and-remote-repositories/ .)
Una línea más corta y segura:
git branch -d $(git branch --merged | cut -c 3-)
Asegúrate de revisar la bifurcación que aún no está fusionada, antes de ejecutarla. Porque no puedes eliminar la rama en la que estás registrado.
Uno puede configurar Git para eliminar automáticamente las referencias a las ramas remotas eliminadas al recuperar:
git config --global fetch.prune true
Cuando se llama a git fetch
o git pull
después, las referencias a las sucursales remotas eliminadas se eliminan automáticamente.
Usando una variante en la respuesta de @ wisbucky, agregué lo siguiente como un alias a mi archivo ~/.gitconfig
:
pruneitgood = "!f() { /
git remote prune origin; /
git branch -vv | perl -nae ''system(qw(git branch -d), $F[0]) if $F[3] eq q{gone]}''; /
}; f"
Con esto, un simple git pruneitgood
limpiará las sucursales locales y remotas que ya no son necesarias después de las combinaciones.
no estoy seguro de cómo hacerlo todo de una vez, pero git git branch -d <branchname>
eliminará una rama local SOLAMENTE si está completamente fusionada. Tenga en cuenta la minúscula d.
git branch -D <branchname>
(tenga en cuenta que la D mayúscula) eliminará una sucursal local independientemente de su estado fusionado.