tag remote remota rama example eliminar crear cambiar git git-branch

git - remote - Elimine las ramas de seguimiento que ya no estén en el control remoto.



git push tag (25)

¿Existe una forma sencilla de eliminar todas las ramas de seguimiento cuyo equivalente remoto ya no existe?

Ejemplo:

Ramas (locales y remotas)

  • dominar
  • origen / maestro
  • origen / bug-fix-a
  • origen / bug-fix-b
  • origen / bug-fix-c

A nivel local, solo tengo una rama maestra. Ahora necesito trabajar en bug-fix-a , así que lo compruebo, trabajo en él y presiono los cambios en el control remoto. A continuación hago lo mismo con bug-fix-b .

Ramas (locales y remotas)

  • dominar
  • corrección de errores-a
  • corrección de errores-b
  • origen / maestro
  • origen / bug-fix-a
  • origen / bug-fix-b
  • origen / bug-fix-c

Ahora tengo maestro de sucursales locales, corrección de errores , corrección de errores , b . El mantenedor de la rama maestra combinará mis cambios en la maestra y eliminará todas las ramas que ya haya fusionado.

Así que el estado actual es ahora:

Ramas (locales y remotas)

  • dominar
  • corrección de errores-a
  • corrección de errores-b
  • origen / maestro
  • origen / bug-fix-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 así como el comando existente git remote prune origin , pero más bien como git local prune origin .


Solución de Windows

Para Microsoft Windows Powershell:

git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Trim().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().Trim().Split(" ")[0]} obtiene el nombre de la rama

% {git branch -d $_} borra la rama


Aquí hay una solución que utilizo para la cáscara de pescado. Probado en Mac OS X 10.11.5 , fish 2.3.0 y git 2.8.3 .

function git_clean_branches set base_branch develop # work from our base branch git checkout $base_branch # remove local tracking branches where the remote branch is gone git fetch -p # find all local branches that have been merged into the base branch # and delete any without a corresponding remote branch set local for f in (git branch --merged $base_branch | grep -v "/(master/|$base_branch/|/*/)" | awk ''//s*/w*/s*/ {print $1}'') set local $local $f end set remote for f in (git branch -r | xargs basename) set remote $remote $f end for f in $local echo $remote | grep --quiet "/s$f/s" if [ $status -gt 0 ] git branch -d $f end end end

Algunas notas:

Asegúrate de establecer la base_branch correcta. En este caso utilizo develop como la rama base, pero podría ser cualquier cosa.

Esta parte es muy importante: grep -v "/(master/|$base_branch/|/*/)" . Se asegura de que no elimine maestro o su rama base.

Uso git branch -d <branch> como precaución adicional, para no eliminar ninguna rama que no haya sido completamente fusionada con HEAD anterior o actual.

Una forma fácil de probar es reemplazar git branch -d $f con echo "will delete $f" .

Supongo que también debo agregar: ¡UTILICE A SU PROPIO RIESGO!


Basado en la sugerencia de Git: eliminar viejas sucursales locales , que se parece a la solución de jason.rickman, implementé un comando personalizado para este propósito llamado git ido usando Bash:

$ git gone usage: git gone [-pndD] [<branch>=origin] OPTIONS -p prune remote branch -n dry run: list the gone branches -d delete the gone branches -D delete the gone branches forcefully EXAMPLES git gone -pn prune and dry run git gone -d delete the gone branches

git gone -pn combina la poda y el listado de las ramas "ido":

$ git gone -pn bport/fix-server-broadcast b472d5d2b [origin/bport/fix-server-broadcast: gone] Bump modules fport/rangepos 45c857d15 [origin/fport/rangepos: gone] Bump modules

Luego puedes apretar el gatillo usando git gone -d o git gone -D .

Notas

  • La expresión regular que utilicé es "$BRANCH/.*: gone]" donde $BRANCH normalmente sería origin . Esto probablemente no funcionará si su salida de Git está localizada en francés, etc.
  • Sebastian Wiesner también lo portó a Rust para los usuarios de Windows. Ese también se llama git ido .

Basado en la información anterior, esto funcionó para mí:

git br -d `git br -vv | grep '': gone] '' | awk ''{print $1}'' | xargs`

Elimina todas las sucursales locales con '': gone] '' en el control remoto.


Despues del comando

git fetch -p

elimina las referencias remotas, cuando se ejecuta

git branch -vv

se mostrará ''ido'' como el 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

Por lo tanto, puede escribir un script simple para eliminar las sucursales locales que se han ido a control remoto:

git fetch -p && for branch in `git branch -vv | grep '': gone]'' | awk ''{print $1}''`; do git branch -D $branch; done


Elimine todas las ramas que se hayan fusionado en el maestro, pero no intente eliminar el propio maestro:

git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)

o agregar un alias:

alias gitcleanlocal="git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"

Explicación:

git checkout master checkout maestro rama

git pull origin master asegura que la sucursal local tenga todos los cambios remotos fusionados

git fetch -p elimina las referencias a ramas remotas que han sido eliminadas

git branch -d $(git branch master --merged | grep master -v) elimina todas las sucursales que se han fusionado en master, pero no intentes eliminar master en sí mismo


Encontré la respuesta aquí: ¿Cómo puedo eliminar todas las ramas de git que se han fusionado?

git branch --merged | grep -v "/*" | xargs -n 1 git branch -d

Asegúrate de que tenemos maestro

Puede asegurarse de que el master , o cualquier otra rama, no se elimine agregando otro grep después de la primera. En ese caso irías:

git branch --merged | grep -v "/*" | grep -v "YOUR_BRANCH_TO_KEEP" | xargs -n 1 git branch -d

Entonces, si quisiéramos master , develop y staging por ejemplo, iríamos:

git branch --merged | grep -v "/*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d

Haz de esto un alias

Como es un poco largo, es posible que desee agregar un alias a su .zshrc o .bashrc . El mío se llama gbpurge (para git branches purge ):

alias gbpurge=''git branch --merged | grep -v "/*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d''

Luego recargue su .bashrc o .zshrc :

. ~/.bashrc

o

. ~/.zshrc


Esto eliminará toda la ramificación local combinada excepto la referencia maestra local y la que se está utilizando actualmente:

git branch --merged | grep -v "*" | grep -v "master" | xargs git branch -d

Y esto eliminará todas las ramas que ya han sido eliminadas del repositorio remoto referenciado por " origen ", pero aún están disponibles localmente en " remotos / origen ".

git remote prune origin


Esto eliminará todas las ramas remotas que no están presentes localmente (en ruby):

bs = `git branch`.split; bs2 = `git branch -r | grep origin`.split.reject { |b| bs.include?(b.split(''/'')[1..-1].join(''/'')) }; bs2.each { |b| puts `git push origin --delete #{b.split(''/'')[1..-1].join(''/'')}` }

Explicado:

# local branches bs = `git branch`.split # remote branches bs2 = `git branch -r | grep origin`.split # reject the branches that are present locally (removes origin/ in front) bs2.reject! { |b| bs.include?(b.split(''/'')[1..-1].join(''/'')) } # deletes the branches (removes origin/ in front) bs2.each { |b| puts `git push origin --delete #{b.split(''/'')[1..-1].join(''/'')}` }


Esto funcionó para mí:

git branch -r | awk ''{print $1}'' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk ''{print $1}'' | xargs git branch -d


La coincidencia de patrones para "desaparecido" en la mayoría de las otras soluciones me dio un poco de miedo. Para estar más seguro, utiliza el indicador --format para extraer el estado de seguimiento ascendente de cada sucursal.

Necesitaba una versión compatible con Windows, por lo que se eliminan todas las ramas que aparecen como "desaparecidas" con Powershell:

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | ? { $_ -ne "" } | % { git branch -D $_ }

La primera línea enumera el nombre de las sucursales locales cuya rama ascendente está "desaparecida". La siguiente línea elimina las líneas en blanco (que se emiten para las ramas que no están "desaparecidas"), luego el nombre de la rama se pasa al comando para eliminar la rama.


La mayoría de estas respuestas no responden realmente a la pregunta original. Hice un montón de excavaciones y this fue la solución más limpia que encontré. Aquí hay una versión un poco más completa de esa respuesta:

  1. Echa un vistazo a su rama por defecto. Generalmente git checkout master
  2. Ejecutar git fetch -p && git branch -vv | awk ''/: gone]/{print $1}'' | xargs git branch -d git fetch -p && git branch -vv | awk ''/: gone]/{print $1}'' | xargs git branch -d

Explicación:

Trabaja podando las ramas de seguimiento y luego borrando las locales que muestran que se han "ido" en git branch -vv .

Notas:

Si su idioma está configurado en otro idioma que no sea el inglés, deberá cambiar la palabra apropiada. Las ramas que son locales solamente no serán tocadas. Las sucursales que se eliminaron en el control remoto pero no se fusionaron mostrarán una notificación, pero no se eliminarán en local. Si desea eliminarlos también cambie -d a -D .


Nada de esto era realmente correcto para mí. 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). También 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.

Esto es en última instancia, lo que terminó 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: En el comando config, uso la opción -d para git branch lugar de -D , como lo hago en mi configuración real. Uso -D porque no quiero escuchar a Git quejarse de las ramas no fusionadas. 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.


No creo que haya un comando incorporado para hacer esto, pero es seguro hacer lo siguiente:

git checkout master git branch -d bug-fix-a

Cuando use -d , git rechazará eliminar la rama a menos que esté completamente fusionada con HEAD o su rama de seguimiento remoto ascendente. Por lo tanto, siempre se puede hacer un bucle sobre la salida de git for-each-ref y tratar de eliminar cada rama. El problema con este enfoque es que sospecho que probablemente no desee que se elimine bug-fix-d solo porque origin/bug-fix-d contiene su historial. En su lugar, podría crear un script similar al siguiente:

#!/bin/sh git checkout master && for r in $(git for-each-ref refs/heads --format=''%(refname:short)'') do if [ x$(git merge-base master "$r") = x$(git rev-parse --verify "$r") ] then if [ "$r" != "master" ] then git branch -d "$r" fi fi done

Advertencia: no he probado este script; utilícelo solo con cuidado ...


No estoy seguro de cuánto tiempo, pero uso git-up ahora, lo cual se encarga de eso.

Lo hago y empieza a rastrear nuevas sucursales y borra las antiguas.

Solo para dejarlo claro, no es un comando git listo para usar: https://github.com/aanand/git-up

Por cierto, también esconde un árbol sucio y hace rebases aún con solo git up .

Espero que sea de utilidad para alguien.


Normalmente no respondería una pregunta que ya tenga 16 respuestas, pero todas las demás respuestas son incorrectas, y la respuesta correcta es muy simple. La pregunta dice: "¿Existe una forma sencilla de eliminar todas las ramas de seguimiento cuyo equivalente remoto ya no existe?"

Si "simple" significa no es frágil, no es peligroso y no se confía en herramientas que no todos los lectores tendrán, entonces la respuesta correcta es: no.

Algunas respuestas son simples, pero no hacen lo que se les pidió. Otros hacen lo que se les pidió, pero no son simples: todos se basan en analizar la salida de Git (y la salida de porcelana para arrancar en la mayoría de los casos) a través de comandos de manipulación de texto o lenguajes de script, que pueden no estar presentes en todos los sistemas.

Más información: https://.com/a/20107184/587365 y https://.com/a/26152574/587365

Si desea hacer esto de manera segura, para el caso de uso en la pregunta (recolectando basura en las ramas de seguimiento que se han eliminado en el servidor pero aún existen como sucursales locales) y solo con comandos de Git de alto nivel, debe

  • git fetch --prune (o git fetch -p , que es un alias, o git prune remote origin que hace lo mismo sin recuperar, y probablemente no sea lo que desea la mayoría del tiempo).
  • Tenga en cuenta las sucursales remotas que se informan como eliminado. O, para encontrarlos más adelante, git branch -v (cualquier rama de seguimiento huérfana se marcará "[desaparecido]").
  • git branch -d [branch_name] en cada rama de seguimiento huérfana

Explicación de fondo

Para comprender lo que está sucediendo, debe apreciar que, en la situación de seguimiento de sucursales, no tiene una, sino tres. (Y recuerde que "rama" significa simplemente un puntero a una confirmación).

Dada una feature/X rama de seguimiento feature/X , el repositorio remoto (servidor) tendrá esta rama y lo llamará feature/X Su repositorio local tiene una rama remotes/origin/feature/X que significa que "esto es lo que me dijo el control remoto su característica / rama X, la última vez que hablamos", y finalmente, el repositorio local tiene una feature/X rama feature/X que apunta a su último compromiso, y está configurado para "rastrear" los remotes/origin/feature/X , lo que significa que puede tirar y empujar para mantenerlos alineados.

En algún momento, alguien ha eliminado la feature/X en el control remoto. A partir de ese momento, se queda con su feature/X local (que probablemente ya no desee más, ya que el trabajo en la función X probablemente está terminado), y sus remotes/origin/feature/X que ciertamente son inútiles porque es el único El propósito era recordar el estado de la rama del servidor.

Y Git te permitirá limpiar automáticamente los remotes/origin/feature/X redundantes, eso es lo que git fetch --prune hace - pero por alguna razón, no te permite eliminar automáticamente tu propia feature/X ... A pesar de que su feature/X todavía contiene la información de seguimiento huérfana, tiene la información para identificar las ramas de seguimiento anteriores que se han fusionado por completo. (Después de todo, puede brindarle la información que le permite realizar la operación usted mismo).


Parece que la solución está aquí - https://.com/a/1072178/133986

En resumen, git remote prune hace la magia.


Puede ser útil para algunos, una simple línea para borrar todas las sucursales locales, excepto dominar y desarrollar

git branch | grep -v "master" | grep -v "develop" | xargs git branch -D


Se me ocurrió este guión de bash. Siempre se mantienen las ramas en develop , qa , master .

git-clear() { git pull -a > /dev/null local branches=$(git branch --merged | grep -v ''develop'' | grep -v ''master'' | grep -v ''qa'' | sed ''s/^/s*//'') branches=(${branches//;/ }) if [ -z $branches ]; then echo ''No branches to delete...'' return; fi echo $branches echo ''Do you want to delete these merged branches? (y/n)'' read yn case $yn in [^Yy]* ) return;; esac echo ''Deleting...'' git remote prune origin echo $branches | xargs git branch -d git branch -vv }


Sin embargo, otra respuesta para la pila, se basa en https://.com/a/48411554/2858703 (lo que me gusta porque parece eliminar cualquier ambigüedad acerca de a dónde se gone] coincidirá en la salida de la git branch ) pero añadiendo un * nix doblado:

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" / | sed ''s,^refs/heads/,,;/^$/d'' / | xargs git branch -D

Tengo esto envuelto en un script de git-gone en mi camino:

#!/usr/bin/env bash action() { ${DELETE} && xargs git branch -D || cat } get_gone() { git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" / | sed ''s,^refs/heads/,,;/^$/d'' } main() { DELETE=false while [ $# -gt 0 ] ; do case "${1}" in (-[dD] | --delete) DELETE=true ;; esac shift done get_gone | action } main "${@}"

Nota: la opción --format parece ser bastante nueva; Necesitaba actualizar git de 2.10.algo a 2.16.3 para obtenerlo.


Uso este método para tener más control.

git branch -D $(git branch | grep -v "master" | grep -v "develop")

Esto es quitar cualquier rama no nombrada: master o develop .


Utilizo un método corto para hacer el truco, te recomiendo que hagas lo mismo, ya que podría ahorrar algunas horas y darte más visibilidad.

Simplemente agregue el siguiente fragmento de código en su .bashrc (.bashprofile en macos).

git-cleaner() { git fetch --all --prune && git branch --merged | grep -v -E "/bmaster|preprod|dmz/b" | xargs -n 1 git branch -d ;};

  1. Trae todos los controles remotos
  2. Obtener solo ramas fusionadas de git
  3. Eliminar de esta lista las ramas "protegidas / importantes"
  4. Eliminar el resto (por ejemplo, ramas limpias y fusionadas)

Tendrá que editar el greg regex para que se ajuste a sus necesidades (aquí, evita que se eliminen master, preprod y dmz)


git remote prune origin ciruelas pasas de seguimiento no 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 la git branch --merged . La lista podría incluir master u otras ramas que preferiría no eliminar.

Para darse la oportunidad de editar la lista antes de eliminar sucursales, 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


git fetch -p

Esto eliminará todas las ramas que no se rastrean de forma remota.


grep gone <(git branch -v) | cut -d '' '' -f 3 | xargs git branch -d

El comando anterior se puede usar para buscar ramas que se combinan y eliminan en remoto y elimina la rama local que ya no está disponible en remoto