¿Cómo puedo iterar a través de todas las ramas locales en mi repositorio usando el script bash? Necesito iterar y verificar si hay alguna diferencia entre la rama y algunas ramas remotas. Ex
for branch in $(git branch);
do
git log --oneline $branch ^remotes/origin/master;
done
Necesito hacer algo como se indicó anteriormente, pero el problema al que me enfrento es $ (git branch) me da las carpetas dentro de la carpeta del repositorio junto con las ramas presentes en el repositorio.
¿Es esta la forma correcta de resolver este problema? ¿O hay otra forma de hacerlo?
Gracias
for b in "$(git branch)"; do git branch -D $b; done
Respuestas:
No debe usar git branch al escribir scripts. Git proporciona una interfaz de "plomería" que está diseñada explícitamente para su uso en secuencias de comandos (muchas implementaciones actuales e históricas de los comandos de Git normales (agregar, verificar, fusionar, etc.) utilizan esta misma interfaz).
El comando de plomería que desea es git for-each-ref :
Nota: No necesita el
remotes/
prefijo en la referencia remota a menos que tenga otras referencias que haganorigin/master
coincidir varios lugares en la ruta de búsqueda del nombre de referencia (consulte "Un nombre de referencia simbólico. ..." en la sección Especificación de revisiones de git-rev-parse (1) ). Si usted está tratando de evitar la ambigüedad explicitamente, y luego ir con el nombre completo ref:refs/remotes/origin/master
.Obtendrá un resultado como este:
Puede canalizar esta salida a sh .
Si no le gusta la idea de generar el código de shell, puede renunciar a un poco de robustez * y hacer esto:
* Los nombres de referencia deben estar a salvo de la división de palabras del shell (consulte git-check-ref-format (1) ). Personalmente, me quedaría con la versión anterior (código de shell generado); Estoy más seguro de que nada inapropiado puede pasar con él.
Dado que especificó bash y admite matrices, puede mantener la seguridad y aún evitar generar las entrañas de su bucle:
Podría hacer algo similar con
$@
si no está usando un shell que admita matrices (set --
para inicializar yset -- "$@" %(refname)
agregar elementos).fuente
--merged
, tendría que duplicar la lógica en git branch? Tiene que haber una mejor manera de hacer esto.git for-each-ref refs/heads | cut -d/ -f3-
git for-each-ref refs/heads --format='%(refname)'
for-each-ref
ahora admite todos los selectores de rama como--merged
y,git branch
ygit tag
ahora se implementan en términos degit for-each-ref
sí mismos, al menos para los casos existentes en la lista. (La creación de nuevas ramas y etiquetas no es, y no debería ser, parte defor-each-ref
.)Esto se debe a que
git branch
marca la rama actual con un asterisco, por ejemplo:por lo que se
$(git branch)
expande a eg* master mybranch
, y luego se*
expande a la lista de archivos en el directorio actual.No veo una opción obvia para no imprimir el asterisco en primer lugar; pero podrías cortarlo:
fuente
$(git branch | sed -e s/\\*//g)
.3-
solución.$(git branch | sed 's/^..//')
$(git branch | tr -d " *")
El bash incorporado
mapfile
, está construido para estotodas las ramas de git:
git branch --all --format='%(refname:short)'
todas las sucursales locales de git:
git branch --format='%(refname:short)'
todas las ramas de git remotas:
git branch --remotes --format='%(refname:short)'
iterar a través de todas las ramas de git:
mapfile -t -C my_callback -c 1 < <( get_branches )
ejemplo:
para la situación específica del PO:
fuente: enumera todas las ramas locales de git sin un asterisco
fuente
Repetiré como por ejemplo:
fuente
Sugeriría
$(git branch|grep -o "[0-9A-Za-z]\+")
si sus sucursales locales se nombran solo por dígitos, az y / o letras de AZfuente
La respuesta aceptada es correcta y realmente debería ser el enfoque utilizado, pero resolver el problema en bash es un gran ejercicio para comprender cómo funcionan los shells. El truco para hacer esto usando bash sin realizar manipulación de texto adicional, es asegurarse de que la salida de la rama git nunca se expanda como parte de un comando que ejecutará el shell. Esto evita que el asterisco se expanda en la expansión del nombre de archivo (paso 8) de la expansión del shell (consulte http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html )
Use bash while build con un comando de lectura para cortar la salida de la rama git en líneas. El '*' se leerá como un carácter literal. Utilice una declaración de caso para que coincida, prestando especial atención a los patrones de coincidencia.
Los asteriscos tanto en la construcción del caso bash como en la sustitución de parámetros deben escaparse con barras invertidas para evitar que el shell los interprete como caracteres de coincidencia de patrones. Los espacios también se escapan (para evitar la tokenización) porque literalmente está haciendo coincidir '*'.
fuente
Opción más fácil de recordar en mi opinión:
git branch | grep "[^* ]+" -Eo
Salida:
La opción -o de Grep (--only-matching) restringe la salida a solo las partes coincidentes de la entrada.
Dado que ni el espacio ni * son válidos en los nombres de las ramas de Git, esto devuelve la lista de ramas sin los caracteres adicionales.
Editar: si está en el estado de 'cabeza separada' , deberá filtrar la entrada actual:
git branch --list | grep -v "HEAD detached" | grep "[^* ]+" -oE
fuente
Lo que terminé haciendo, aplicado a su pregunta (e inspirado por la mención de ccpizza
tr
):git branch | tr -d ' *' | while IFS='' read -r line; do git log --oneline "$line" ^remotes/origin/master; done
(Yo uso muchos bucles while. Mientras que para cosas particulares definitivamente querrás usar un nombre de variable puntiagudo ["rama", por ejemplo], la mayoría de las veces solo me preocupa hacer algo con cada línea de entrada. Usando 'línea' aquí en lugar de 'rama' es un guiño a la reutilización / memoria muscular / eficiencia).
fuente
A partir de la respuesta de @ finn (¡gracias!), Lo siguiente le permitirá iterar sobre las ramas sin crear un script de shell intermedio. Es lo suficientemente robusto, siempre que no haya nuevas líneas en el nombre de la rama :)
El bucle while se ejecuta en una subcapa, lo que generalmente está bien a menos que esté configurando variables de shell a las que desea acceder en el shell actual. En ese caso, usa la sustitución de procesos para revertir la tubería:
fuente
Si estás en este estado:
Y ejecuta este código:
Obtendrás este resultado:
fuente
for b in "$(git branch)"; do git branch -D $b; done
Mantenlo simple
La forma sencilla de obtener el nombre de la rama en un bucle mediante el script bash.
Salida:
fuente
La respuesta de Googlian, pero sin usar para
fuente
Esto usa comandos de plomería de git , que están diseñados para secuencias de comandos. También es simple y estándar.
Referencia: finalización de Bash de Git
fuente