Introducción
Git soporta dos tipos de tags: lightweight, que son solo refs apuntando a commits, y anotados, que son objetos Git completos con metadatos. Usa tags anotados para releases.
Creando
git tag v1.0.0 # lightweight
git tag -a v1.0.0 -m "1.0 GA" # anotado
git tag -s v1.0.0 -m "Signed" # anotado firmado GPG
git tag -a v1.0.0 a1b2c3d -m "..." # etiquetar un commit específico
Qué almacenan los tags anotados
git cat-file -t v1.0.0
# tag
git cat-file -p v1.0.0
# object <commit-sha>
# type commit
# tag v1.0.0
# tagger Ada <[email protected]> 1714300000 +0000
#
# 1.0 GA
Un tag anotado es su propio objeto. Tiene su propio SHA distinto del commit al que apunta, un tagger y fecha, un mensaje, y una firma opcional.
Lo que los tags lightweight no almacenan
Un tag lightweight es solo refs/tags/v1.0.0 que contiene un SHA de commit. No hay mensaje, ni tagger, ni firma. git describe, git tag -v y muchas herramientas de release de CI asumen tags anotados y se comportan extraño con los lightweight.
Inspeccionando
git show v1.0.0
git tag -l --format='%(refname:short) %(objecttype) %(taggername) %(subject)'
Los tags lightweight muestran commit como tipo de objeto; los tags anotados muestran tag.
Firmando y verificando
git tag -s v1.0.0 -m "Signed"
git tag -v v1.0.0
# gpg: Good signature from "Ada Lovelace <[email protected]>"
La firma SSH también está soportada en Git moderno:
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git tag -s v1.1.0 -m "SSH-signed"
Eligiendo
- Usa anotados para releases, cualquier cosa que publiques, cualquier cosa que firmes.
- Usa lightweight para marcadores locales ad hoc (p.ej. "recordar este commit antes de rebasear").
Pusheando tags
git push origin v1.0.0
git push origin --tags
git push --follow-tags # solo tags anotados alcanzables desde commits pusheados
--follow-tags deliberadamente ignora tags lightweight, lo cual normalmente es lo que quieres.
Desreferenciamiento de tags
Muchos comandos automáticamente desreferencian un tag anotado al commit al que apunta; algunos no. Usa ^{} para forzar el desreferenciamiento en scripts:
git rev-parse v1.0.0 # SHA del objeto tag (anotado)
git rev-parse v1.0.0^{} # SHA del commit al que apunta
git rev-parse v1.0.0^{commit} # igual, con aserción de tipo
git for-each-ref --format='%(refname:short) %(*objectname)' refs/tags
El placeholder %(*objectname) da el commit desreferenciado para tags y está vacío para refs no-tag. Este patrón es esencial para scripts de release que necesitan un SHA de commit a partir de un nombre de tag.
Errores comunes
Etiquetar releases con un simple git tag v1.0 y perder tagger/fecha/mensaje en los registros de auditoría. Siempre pasa -a o -s. Mover un tag publicado a un nuevo commit ("force-tag"); los usuarios downstream ya cachearon el SHA viejo y pueden no recoger el cambio. Emite v1.0.1 en su lugar. Usar tags lightweight como marcadores nombrados compartidos entre un equipo; si debes compartir, prefiere branches o tags anotados. Finalmente, esperar que git describe funcione sin tags anotados; por defecto solo cuenta los anotados (--tags opta por incluir lightweight, con advertencias).