usar tipos tag repositorio remove qué podemos partir para otro oneline nuevo log hace existen etiquetas crear git git-remote git-tag

tipos - Git-Revisa una etiqueta remota cuando dos remotos tienen el mismo nombre de etiqueta



tipos de etiquetas en git (4)

Resumen ejecutivo: lo que quiere lograr es posible, pero primero debe inventar etiquetas remotas.

Esto se hace con una serie de refspecs, uno para cada control remoto. El resto de esto se trata de lo que son, cómo funcionan, etc.

Su pregunta se refiere a la extracción de una "etiqueta remota", pero Git no tiene etiquetas remotas, y esto:

pero estoy haciendo algo raro donde tengo muchos controles remotos, y me preocupa lo que suceda si dos controles remotos tienen la misma etiqueta. ¿Hay alguna manera de especificar el control remoto al revisar la etiqueta?

Revela (creo) la fuente de tu confusión.

Retrocedamos por un momento y solo hablemos de lo que Git tiene en un sentido general, que son "referencias". Para ayudar a consolidar la idea, las formas específicas de referencias incluyen los nombres de sus sucursales locales ( master , devel , feature , etc.), "nombres de sucursales remotas" como origin/master y stuff_from_bobs_computer/master , y nombres de etiquetas. Cosas como el "alijo" de Git también usan referencias, e incluso HEAD es una referencia, aunque es muy especial, y generalmente es una referencia "simbólica". El punto aquí es que Git tiene muchas formas de referencias, y todas realmente funcionan de la misma manera al final: un nombre de referencia resuelve, al final, uno de esos grandes valores SHA-1, 676699a0e0cdfd97521f3524c763222f1c30a094 o lo que sea.

La mayoría de las referencias (las excepciones son cosas como HEAD , ORIG_HEAD , MERGE_HEAD y algunas otras), en realidad están escritas con nombres que comienzan con refs/ . Estos se guardan en una especie de estructura de directorio o carpeta, 1 con subdirectorios: refs/tags/ contiene sus etiquetas, 2 refs/heads/ contiene todas sus sucursales, y refs/remotes/ contiene todas sus sucursales remotas.

Las ramas remotas están subdivididas aún más por el nombre del remoto: refs/remotes/stuff_from_bobs_computer/ contiene todas las ramas remotas de origin , mientras que refs/remotes/stuff_from_bobs_computer/ contiene toda la stuff_from_bobs_computer remote-sucursales. Si tiene muchos controles remotos, tiene muchos subdirectorios dentro de refs/remotes/ .

Acabo de mencionar que tus etiquetas están todas en refs/tags/ . ¿Qué pasa con las etiquetas de los controles remotos, todas las etiquetas en todos los diferentes controles remotos? Bueno, de nuevo, git no tiene "etiquetas remotas". Git tiene "sucursales remotas", pero en realidad son todas locales. Se almacenan en su repositorio, bajo los refs/remotes/ encabezado.

Cuando su Git se pone en contacto con un "remoto", generalmente a través del git fetch remote , pero también para push (y el paso de clone inicial), su Git le pregunta al remoto Git 3 la pregunta: "¿Qué sucursales locales tiene? ¿Qué son sus valores SHA-1? " Esto es, de hecho, cómo funciona la fetch : como una descripción simplificada, el proceso de búsqueda consiste en preguntar al Git remoto "hey, whaddaya got?" y te da un conjunto de nombres y SHA-1. Tu Git luego verifica si tiene los mismos SHA-1. Si es así, la conversación está hecha; si no, tu Git luego dice "ok, necesito lo que haya en el (los) compromiso (s) para estos SHA-1s", que en realidad resulta ser otro grupo de SHA-1s, y tu Git y los suyos lo discuten para averiguar qué archivos y qué necesita también, todos identificados por SHA-1. Su Git trae esos objetos y mete los nuevos SHA-1 en sus refs/remotes/ , bajo el nombre del control remoto y luego bajo los nombres de sus sucursales locales.

Si pides etiquetas con tu fetch , tu Git hace un poco más. 4 En lugar de solo preguntarles a sus Git sobre sus sucursales, tu Git también les pregunta a ellos sobre sus etiquetas. Nuevamente, su Git solo te da una lista de nombres y SHA-1. Su Git luego trae los objetos subyacentes necesarios y luego, aquí está la clave de todo el problema, escribe sus nombres de etiquetas en sus refs/tags/ .

Entonces, ¿qué sucede cuando vas al origin remoto y le pides etiquetas y dice "Tengo refs/tags/pinky y refs/tags/brain ", es que esto crea, para ti, las etiquetas locales pinky y brain , también se llama refs/tags/pinky y refs/tags/brain en el espacio de nombre de referencia.

Ahora vas a la computadora de Bob (el control remoto llamado stuff_from_bobs_computer arriba) y le pides etiquetas. Le refs/tags/spinal_cord la neurología, en lugar de Warner Brothers y Sister, y sus etiquetas son refs/tags/spinal_cord y refs/tags/spinal_cord refs/tags/brain , y la segunda probablemente no esté relacionada con la de origin . ¡UH oh!

Exactamente lo que sucede aquí se complica un poco, 5 pero en resumen, esto es solo una mala situación y probablemente deberías evitarlo si es posible. Hay dos maneras fáciles (bueno ...) de evitarlo. Uno, con el inconveniente obvio, es: simplemente no obtener sus etiquetas. Entonces no tendrás ningún conflicto de etiquetas. El otro es: mantenga todas sus etiquetas separadas una de la otra (y quizás también de la suya). Resulta que el segundo no es realmente tan difícil. Solo tienes que "inventar" etiquetas remotas.

Echemos un vistazo rápido a cómo Git implementa en realidad "sucursales remotas", y cómo funciona la función de fetch --tags . Ambos usan el mismo mecanismo básico, lo que git llama "refspecs".

En su forma más simple, una refspec se ve como dos nombres de ref con dos puntos entre ellos: refs/heads/master:refs/heads/master , por ejemplo. De hecho, incluso puedes dejar de lado los refs/heads/ y Git lo pondrá para ti, 6 y algunas veces también puedes dejar de lado los dos puntos y el nombre repetido. Este es el tipo de cosa que usa con git push : git push origin branch significa empujar a origin , usando refs/heads/branch , y llamarlo refs/heads/branch cuando llega a "su" Git también.

Sin embargo, para la fetch archivos remotos, obtienes una refspec que se ve así:

+refs/heads/*:refs/remotes/origin/*

El + en la parte frontal significa "fuerza", y los * s hacen lo obvio. Tu Git habla con los suyos y obtiene una lista de referencias. Aquellos que coinciden con refs/heads/* , el suyo los trae (junto con sus objetos de repositorio según sea necesario), pero luego los guarda en su repositorio bajo nombres que comienzan con refs/remotes/origin/ , y ahora tiene todas las "ramas remotas "De origin . 7

Cuando ejecuta git fetch --tags , su git agrega +refs/tags/*:refs/tags/* a los refspecs que usa. 8 Eso trae sus etiquetas y las pone en sus etiquetas locales. Así que todo lo que tienes que hacer es dar a fetch una refspec que se parece a:

+refs/tags/*:refs/rtags/origin/*

y de repente, tendrá un nuevo nombre de espacio de "etiquetas remotas" bajo refs/rtags/ (solo para el origin , en este caso). Es seguro usar la + fuerza-bandera aquí ya que solo está actualizando su copia de sus etiquetas: si han movido a la fuerza (o eliminado y recreado) una etiqueta, usted mueve la copia. También puede querer o incluso necesitar el comportamiento de --no-tags , que puede obtener al especificar --no-tags en la línea de comando o, bueno, consulte el siguiente párrafo.

El único elemento útil que queda por conocer es que git fetch obtiene sus refspecs predeterminados, para cualquier control remoto dado, del archivo de configuración de Git. 9 Si examina su archivo de configuración de Git, verá una línea fetch = debajo de cada control remoto, utilizando la cadena +refs/heads/*:refs/remotes/ remote-name /* . Puede tener tantas líneas fetch = como desee por control remoto, por lo que puede agregar una para traer sus etiquetas, pero colóquelas en el espacio de nombres de las "etiquetas remotas" (re) inventadas recientemente. También es posible que desee que --no-tags el predeterminado para este control remoto configurando tagOpt = --no-tags en esta misma sección. Ver este comentario por el usuario200783 para más detalles.

Al igual que con todos los comandos de Git que resuelven un nombre para un SHA-1 en bruto, entonces puede git checkout con el nombre de referencia completo para ingresar al modo "HEAD desasociado" en el SHA-1 correspondiente:

git checkout refs/rtag/stuff_from_bobs_computer/spinal_cord

Como Git no tiene la idea de "etiquetas remotas" incorporadas, debe deletrear el formulario largo (consulte gitrevisions para obtener más información).

1 De hecho, es un directorio real, en .git/refs . Sin embargo, también hay un formulario "empaquetado" para las referencias, que termina en .git/packed-refs . La forma empaquetada está diseñada para ahorrar tiempo y esfuerzo con referencias que no cambian a menudo (o en absoluto, como es común con las etiquetas). También se está realizando un esfuerzo continuo para volver a escribir el sistema de almacenamiento "back-end" para referencias, por lo que en algún momento, mucho de esto puede cambiar. Este cambio es necesario para los sistemas Windows y Mac. Git cree que los nombres de las ramas y las etiquetas distinguen entre mayúsculas y minúsculas: que puedes polish ramas para el material de polish de tus zapatos y polish salchichas. Las versiones empaquetadas distinguen entre mayúsculas y minúsculas, así que esto funciona; pero las versiones almacenadas en los archivos a veces no lo son , ¡así que no!

2 Aquí estoy repasando la diferencia entre etiquetas ligeras y anotadas. Las etiquetas anotadas son objetos reales en el repositorio, mientras que las etiquetas livianas son etiquetas en las refs/tags/ espacio. Sin embargo, en general, cada etiqueta anotada tiene una etiqueta ligera correspondiente, por lo que para este uso en particular, funcionan de la misma manera.

3 Casi siempre es otro repositorio de Git, aunque ahora hay adaptadores para Git to Mercurial, svn, etc. Tienen sus propios trucos para simular ser repositorios de Git. Además, esta descripción no pretende ser definitiva: la secuencia real de las operaciones se codifica para la eficiencia de transferencia, en lugar de para dar sentido a los humanos.

4 He pasado por alto un poco de rareza especial acerca de la fetch y la clone simple aquí, es decir, las versiones sin --tags . Las versiones con --tags son fáciles de explicar: traen todas las etiquetas usando las refspecs que he descrito aquí, y, al menos en Git 2.10 y 2.11, --tags también realiza actualizaciones forzadas, como si el indicador de forzado + fueron puestos. Pero a menos que --no-tags explícitamente --no-tags , una búsqueda simple (y clonación) trae algunas etiquetas. Lo único que hace es buscar etiquetas que se correspondan con los objetos que vienen debido a la búsqueda, y agrega esas (sin forzar actualizaciones) a su nombre de espacio de etiquetas (global). Sin --tags tu Git no sobrescribirá tus propias etiquetas existentes; con --tags , su Git sobrescribirá sus propias etiquetas existentes, al menos en Git 2.10, por experimentos reales realizados a principios de 2017.

5 Las versiones anteriores de Git aplicaban reglas de "ramificación" a las etiquetas durante la inserción (pero no necesariamente a la obtención), permitiendo una actualización de la etiqueta si era un avance rápido y, de lo contrario, requerían la marca de fuerza. La versión más reciente de git push solo requiere la etiqueta de fuerza. El comando refspec de --tags no tiene el indicador de fuerza establecido, pero actúa como si lo tuviera. No he experimentado con el empuje con --tags . Hay una característica especial más de git fetch acerca de --tags vs --no-tags vs refspecs explícitos, que tiene que ver con cómo funciona --prune . La documentación dice que --prune aplica a cualquier --prune explícita refs refs/tags/ refspecs, pero no a la implícita --tags refspec. Tampoco he experimentado para verificar esto.

6 Para que tu Git complete refs/heads/ o refs/tags/ for you, tu Git tiene que ser capaz de averiguar a cuál te refieres. Hay algunos casos donde lo hace, y algunos donde no lo hace. Si su Git no logra resolverlo, recibirá un mensaje de error y podrá intentarlo nuevamente, pero en los scripts siempre debe hacerlo de forma explícita para obtener un comportamiento más predecible. Si solo está ejecutando git push para empujar una rama existente, casi siempre puede dejar que su Git lo descubra.

7 Dejar de lado los dos puntos y el segundo nombre no funciona tan bien para git fetch : ¡le dice a su Git que no actualice sus propias referencias en absoluto! Esto parece sin sentido, pero en realidad puede ser útil, porque git fetch siempre escribe el archivo especial FETCH_HEAD . Puede pescar los ID de objeto de Git (SHA-1) fuera del archivo especial y ver qué se recuperó. Esto es principalmente un remanente de versiones muy tempranas de Git, antes de que se inventaran las sucursales de seguimiento remoto.

8 El refspec que usa git fetch --tags y git push --tags está precompilado internamente, en la versión 2.10 de Git, y se maneja mediante un código de caso especial. La forma precompilada no tiene el conjunto de bandera + ; sin embargo, la experimentación muestra que las etiquetas recuperadas se actualizan a la fuerza en Git 2.10 / 2.11. Recuerdo que experimenté hace años con Git 1.x, y --tags que estas --tags -fetched tags no se actualizaron a la fuerza, así que creo que esto ha cambiado, pero eso puede ser solo una memoria defectuosa. En cualquier caso, si está (re) inventando etiquetas remotas, lo más probable es que no quiera usar una --tags explícita.

9 De hecho, así es como funcionan los espejos. Por ejemplo, con fetch = +*:* obtienes un espejo de fetch puro. El proceso de búsqueda puede ver todas las referencias. Puedes verlos tú mismo con git ls-remote . También es así como --single-branch funciona: si usa --single-branch durante la clonación, su archivo de configuración de Git mostrará solo una única rama en la línea de búsqueda. Para convertir de rama única a rama completa, simplemente edite la línea para que contenga la entrada de patrón de patrón habitual.

Esperaba que esto funcionara:

git checkout remote/tag_name

pero no lo hace Esto hace:

git checkout tags/tag_name

pero estoy haciendo algo raro donde tengo muchos controles remotos, y me preocupa lo que suceda si dos controles remotos tienen la misma etiqueta. ¿Hay alguna manera de especificar el control remoto al revisar la etiqueta?


1 - Obtener la etiqueta del control remoto con:

git fetch origin --tags

O, para retirar una etiqueta de un uso remoto diferente:

git fetch your_remote --tags

2 Echa un vistazo a la etiqueta corriendo

git checkout tags/<tag_name>

Más aquí: Descargar una etiqueta específica con Git


En mi caso, cuando se agregó una nueva etiqueta al repositorio remoto [Estoy usando Stash], la nueva etiqueta no estaba disponible en el resultado de git tag -l .
Pero pude ver la etiqueta recién agregada usando git ls-remote --tags .
Tuve que ejecutar el siguiente comando para obtener las últimas etiquetas en mi repositorio local:
git pull --tags ejecutar git tag -l ahora también se muestran las etiquetas recién agregadas.

Para pagar una etiqueta, use:
git checkout <tag_name>

Nota: solo es normal ejecutar el estado de git y encontrar un mensaje como este:
HEAD detached at tag_name


Hay algunas preguntas en mi mente:

  • ¿Por qué los diferentes controles remotos tienen un código diferente (en el mismo árbol)?
  • ¿Por qué el código remoto te afecta al revisar las etiquetas?

La cosa es la siguiente:

Cuando verifique una etiqueta utilizando git checkout tags/fancytag , buscará en su repositorio actual (en su máquina) la etiqueta de ajuste.

Si desea verificar una etiqueta de un control remoto específico, primero tiene que fetch (el árbol del control remoto específico) y luego verificarla.