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.
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 | sort
ambos 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.sort
como 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 untag.sort
se había establecido la configuración.
Pero para estar seguro, use al menosgit tag --sort="refname"
(No| sort
necesario) -
no hay necesidad de
grep origin
,sed
osort
(a menos que unbranch.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
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 elgit-fetch-script
código enfast_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 localmenterefs/tags/*
pero como con mi 97716d2 (“fetch
: Agrega un--prune-tags
opción yfetch.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 2011“
fetch
” 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 modificadopull-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.
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