git – Etiquetas con el mismo nombre con una rama

5 minutos de lectura

Estaba un poco asustado por qué diablos git diff branch1 branch2 muestra cosas irrelevantes (era como si estuviera comparando branch1 con una versión ANTERIOR de branch2)

¡Hasta que descubrí que tenemos algunas etiquetas con el mismo nombre con una rama!

Aparte de diff, eso crea problemas en pull/push (error de nombre de referencia ambiguo…), y posiblemente en el pago…

Así que quiero encontrar todas estas etiquetas para poder eliminarlas.

  • El comando simple para esto es git for-each-ref --format='%(refname:short)' | sort | uniq -d, para mostrar todos los nombres cortos con juegos de palabras. Si desea eliminar todas las etiquetas punzadas, git tag -d $(that pipeline).

    – jthill

    23 de septiembre de 2018 a las 3:07


  • En los comandos de git (diff, push, etc.) puede eliminar la ambigüedad, por ejemplo git diff refs/heads/branchname refs/tags/branchname (pero, no obstante, es prudente evitar esta ambigüedad)

    – benjimín

    28 de mayo de 2019 a las 5:18

  • ¡Nunca debe nombrar una etiqueta y una sucursal con el mismo nombre! Referirse: geedew.com/fixing-git-branch-and-tag-name-colisión

    –Eric

    21 de marzo de 2022 a las 4:01

Primero, extraemos todas las etiquetas:

git tag | sort > tags

Y sucursales, si quieres consultar esto con sucursales locales:

git branch | sed -e 's/^[ \t]*//' | sort > branches

O ramas de un control remoto específico, como origin

git branch -r | grep origin/  | sed -e 's:^[ \t]*origin/::' | sort > branches

Después de extraer etiquetas y ramas (en orden), encontramos las líneas comunes en estos 2 archivos:

comm -1 -2 tags branches > bad-tags

Y ver el archivo bad-tags

Entonces podemos eliminarlos todos:

cat bad-tags | xargs git tag -d

La respuesta de saeedgnu está en el camino correcto, pero usa muchos comandos de shell adicionales.

En lugar de usar | sortambos git tag y git branch tener un --sort=<key> opción, con <key> Residencia en git for-each-ref nombres de campo y utilizando un patrón.

De forma predeterminada, el orden de clasificación predeterminado, tanto para sucursales como para etiquetas, ya es por nombreref.

Y desde Git 2.19 (Q3 2018), git branch admite una configuración branch.sortcomo git tag ya tenia una configuracion tag.sort.
Ver cometer 560ae1c (16 ago 2018) por Samuel Maftoul (“).
(Combinado por Junio ​​C Hamano — gitster en cometer d89db6f27 de agosto de 2018)

Entonces:

  • no hay necesidad de ordenar git tag: ya están ordenados por defecto por refname, a menos que un tag.sort se había establecido la configuración.
    Pero para estar seguro, use al menos git tag --sort="refname" (No | sort necesario)
  • no hay necesidad de grep origin, sed o sort (a menos que un branch.sort config había sido establecida): use un patrón y un formato:

    git branch -r --list 'origin/*' --format="%(refname:lstrip=3)"
    

El formato transforma un remotes/origin/aBranchName en aBranchName.
El patrón ‘origin/*‘ se asegura de que estamos seleccionando las ramas remotas del repositorio remoto correcto.

Eso te da comandos puros de git:

git tag --sort="refname" > tags
git branch -r --list 'origin/*' --format="%(refname:lstrip=3)"
comm -1 -2 tags branches > bad-tags

Avatar de usuario de VonC
VonC

Además de generar secuencias de comandos (con comandos de git puros) la cantidad de etiquetas incorrectas, Git 2.20 (cuarto trimestre de 2018) ofrece una alternativa a evitar tener que conseguir etiquetas con el mismo nombre con una rama.

Las reglas utilizadas por “git push” y “git fetch” para determinar si una referencia puede o no actualizarse era inconsistente; específicamente, se permitía buscar para actualizar las etiquetas existentes aunque se supone que las etiquetas son puntos de anclaje inmóviles.
git fetch” se le enseñó a prohibir las actualizaciones de las etiquetas existentes sin el “--force” opción.

Ver cometer 0bc8d71, cometer ae6a470, cometer fe802bd, cometer 8da6128, cometer d931455, cometer 6b0b067, cometer 253b3d4, cometer f08fb8d, cometer 8cd4b7c (31 de agosto de 2018) por Ævar Arnfjörð Bjarmason (avar).
(Combinado por Junio ​​C Hamano — gitster en cometer d39cab317 de septiembre de 2018)

fetch: dejar de golpear las etiquetas existentes sin --force

Cambiar “fetch” para tratar “+” en refspecs (también conocido como --force) para significar que debemos golpear una etiqueta local del mismo nombre.

Esto cambia el comportamiento de larga data de “fetch” añadido en 853a369 (“[PATCH] Recuperación de cabezales múltiples.”, 2005-08-20, Git 0.99.5).
Antes de este cambio, todas las búsquedas de etiquetas tenían efectivamente --force activado.
Ver el git-fetch-script código en fast_forward_local() con el comentario:

No es necesario que las etiquetas apunten a las confirmaciones, por lo que no hay forma de garantizar el “avance rápido” de todos modos.

Ese compromiso y el resto de la historia de “fetch“muestra que el”+” (--force) parte de refpecs solo se concibió para actualizaciones de sucursales, mientras que las etiquetas aceptaron cualquier cambio desde el origen incondicionalmente y derrotaron al objeto de etiqueta local. Cambiar este comportamiento se ha discutido ya en 2011.

El comportamiento actual no tiene sentido para mí, fácilmente da como resultado que las etiquetas locales sean golpeadas accidentalmente.
Podríamos nombrar nuestras etiquetas por control remoto y no poblar localmente refs/tags/*pero como con mi 97716d2 (“fetch: Agrega un --prune-tags opción y fetch.pruneTags config”, 2018-02-09, Git 2.17), es más fácil evitar la implementación actual que corregir la causa raíz.

(Consulte “En Git, ¿cómo sincronizo mis etiquetas con un servidor remoto?”)

Así que este cambio implementa sugerencia #1 del correo electrónico de Jeff de 2011fetch” ahora solo golpea la etiqueta si “+” se proporciona como parte de la especificación de referencia, o si “--force” se proporciona en la línea de comandos.

Esto también lo hace muy simétrico con la forma en que “tag” en sí mismo funciona al crear etiquetas.
Es decir, nos negamos a eliminar las etiquetas existentes a menos que “--force” es proporcionado.
Ahora podemos rechazar todos esos golpes, ya sea golpeando una etiqueta local con “tag“, o buscándolo desde el control remoto con “fetch“.

Ref actualizaciones fuera refs/{tags,heads/* todavía no son simétricos con la forma en que “git push” obras, como se discutió en el recientemente modificado pull-fetch-param.txt documentación.
Este cambio alinea más los dos comportamientos divergentes. No creo que haya ninguna razón por la que “buscar” no pueda converger completamente con el comportamiento utilizado por “push“, pero ese es un tema para otro cambio.

¿Ha sido útil esta solución?