gestor-tareas está a punto de tener su primera versión estable. El equipo quiere poder decir "esto es la 1.0.0" y que dentro de dos años, cuando llegue una incidencia de un cliente que sigue con esa versión, cualquiera pueda situarse exactamente en ese código sin depender de recordar un hash de cuarenta caracteres ni de rebuscar en el git log por fechas.
Para eso están las etiquetas (tags): nombres permanentes que apuntan a un commit concreto. A diferencia de una rama, que avanza cada vez que confirmas, una etiqueta se queda quieta. v1.0.0 significa hoy, mañana y dentro de una década exactamente el mismo commit.
Y hay una segunda cosa que aprender aquí: en la lección 01-04 vimos que la base de datos de Git guarda cuatro tipos de objeto —blob, tree, commit y tag— y del cuarto apenas dijimos nada. Esta lección lo completa. Porque resulta que hay dos clases de etiqueta muy distintas, y la diferencia entre ellas es exactamente si existe o no ese objeto tag.
Contenido
- Qué es una etiqueta y en qué se diferencia de una rama
- Etiquetas ligeras frente a anotadas
- Crear etiquetas
- Listar, buscar y examinar etiquetas
- Etiquetar un commit del pasado
- Versionado semántico
- Enviar etiquetas al remoto
- Borrar etiquetas y por qué no se mueven
- Etiquetas firmadas
git describe: nombrar cualquier commit- Trabajar sobre una etiqueta
- Qué es una etiqueta y en qué se diferencia de una rama
Recuerda la lección 03-01: una rama es un fichero de 41 bytes en .git/refs/heads/ que contiene un hash. Una etiqueta es lo mismo, pero en .git/refs/tags/:
La diferencia no está en el formato sino en el comportamiento:
| Rama | Etiqueta | |
|---|---|---|
| Dónde vive | refs/heads/ |
refs/tags/ |
| ¿Se mueve sola? | Sí: avanza con cada commit | No: nunca |
¿HEAD puede apuntarle? |
Sí | No: te deja en detached HEAD |
| Significado | "Aquí trabajo" | "Esto es un punto concreto" |
Se envía con git push |
Sí (según refspec) | No por defecto |
| Puede tener metadatos propios | No | Sí, si es anotada |
Ese "no se mueve sola" es todo el valor de la herramienta. Si te sitúas en v1.0.0 dentro de tres años, ves exactamente lo que había cuando se publicó, aunque main haya recibido mil commits desde entonces.
gitGraph commit id: "1a4c8d6" commit id: "8b6d3c2" commit id: "9f4c2e8" tag: "v1.0.0" commit id: "c5d9b1e" commit id: "7d3a8f4" tag: "v1.0.1" commit id: "e91d4a8"
main sigue avanzando hacia la derecha; v1.0.0 y v1.0.1 se quedan clavadas donde se pusieron.
- Etiquetas ligeras frente a anotadas
Aquí está el concepto central de la lección.
Una etiqueta ligera (lightweight) es exactamente lo que acabas de ver: un fichero con un hash dentro. Un puntero pelado, sin nada más. No crea ningún objeto nuevo en la base de datos.
Una etiqueta anotada (annotated) crea un objeto tag completo en la base de datos de Git, con su propio hash, que contiene: a qué commit apunta, quién la creó, cuándo, un mensaje, y opcionalmente una firma criptográfica. Y refs/tags/v1.0.0 apunta a ese objeto, no al commit.
Veámoslo con las herramientas de 01-04:
La referencia resuelve directamente a un commit: no hay objeto intermedio.
# Etiqueta anotada
git tag -a v1.0.0 -m "Primera versión estable de gestor-tareas"
git cat-file -t v1.0.0object 9f4c2e8b7d1a5f3c6e9b2d8a4f7c1e5b3d9a6f2c type commit tag v1.0.0 tagger Ana Ferrer <[email protected]> 1754035200 +0200 Primera versión estable de gestor-tareas Incluye el listado de tareas con persistencia en localStorage, el contador de pendientes, el filtro y la exportación a CSV.
Ahí está el cuarto tipo de objeto, por fin en su hábitat natural. Fíjate en la estructura: object (a qué apunta), type (qué es lo apuntado), tag (el nombre), tagger (quién y cuándo) y el mensaje. Y como todo objeto de Git, es inmutable: su hash se calcula sobre ese contenido.
La comparación completa:
| Aspecto | Ligera | Anotada |
|---|---|---|
| Cómo se crea | git tag <nombre> |
git tag -a <nombre> -m "..." |
| Objeto en la base de datos | Ninguno | Un objeto tag |
A qué apunta refs/tags/<n> |
Al commit | Al objeto tag |
| Autor de la etiqueta | No se guarda | Sí (tagger) |
| Fecha de la etiqueta | No se guarda | Sí |
| Mensaje | No | Sí |
| Se puede firmar (GPG/SSH) | No | Sí |
Aparece en git describe |
Solo con --tags |
Sí, por defecto |
--follow-tags la envía |
No | Sí |
| Uso recomendado | Marcas locales y temporales | Versiones publicadas, siempre |
Por qué para publicar versiones se usan siempre las anotadas, en cuatro razones concretas:
- Dejan constancia de quién y cuándo. Un
v1.0.0sin autor ni fecha no responde a "¿quién decidió que esto era la 1.0?". - Llevan un mensaje. Ese mensaje es el sitio natural para las notas de la versión, y viaja con el repositorio.
- Se pueden firmar. Una etiqueta firmada permite verificar criptográficamente que la versión la publicó quien dice.
- Git las trata como ciudadanas de primera.
git describelas prefiere,push --follow-tagssolo envía esas, y varias herramientas del ecosistema las esperan.
La regla práctica es simple: etiqueta ligera = marcador personal desechable; etiqueta anotada = todo lo demás.
- Crear etiquetas
# Ligera, en el commit actual
git tag pruebas-de-hoy
# Anotada, en el commit actual (la forma normal)
git tag -a v1.0.0 -m "Primera versión estable de gestor-tareas"
# Anotada con mensaje largo: sin -m, se abre el editor
git tag -a v1.0.0Cuando se abre el editor, escribe un asunto en la primera línea, una línea en blanco y el cuerpo. Es exactamente la convención de los mensajes de commit (lección 08-01):
gestor-tareas 1.0.0 Primera versión estable, lista para el despliegue del cliente. Incluye: - Alta, listado y borrado de tareas con persistencia en localStorage - Contador de tareas pendientes - Filtro de pendientes - Exportación del listado a CSV
Un aviso sobre los nombres: son referencias de Git, así que valen las mismas reglas que para las ramas (lección 03-06). Sin espacios, sin .., sin ~, ^, :, ?, *, [, sin @{, sin terminar en . ni en .lock. La convención abrumadoramente mayoritaria es v seguida del número: v1.0.0, v2.3.1.
Y una precaución que evita un problema clásico: no uses el mismo nombre para una rama y una etiqueta. Si existen v1.0.0 como rama y como etiqueta, git checkout v1.0.0 es ambiguo, Git avisa y aplica una regla de precedencia que nadie recuerda. Lo vimos de pasada en 04-05 al hablar de refspecs completos; la solución es no crear el problema.
- Listar, buscar y examinar etiquetas
Ordenadas alfabéticamente, que es un orden incorrecto para versiones: v1.10.0 sale antes que v1.2.0. Git lo sabe y tiene una solución:
v:refname ordena entendiendo la semántica de los números de versión, y el - invierte para poner la más nueva arriba. Merece quedarse configurado:
Filtrar por patrón con -l (o --list), que acepta comodines de shell:
Ver la información de cada etiqueta en el listado:
v0.9.0 Version previa a la primera estable v1.0.0 gestor-tareas 1.0.0 v1.0.1 Corrección del foco tras borrar una tarea
Examinar una etiqueta a fondo con git show:
tag v1.0.0 Tagger: Ana Ferrer <[email protected]> Date: Fri Aug 1 10:00:00 2026 +0200 gestor-tareas 1.0.0 Primera versión estable, lista para el despliegue del cliente. commit 9f4c2e8b7d1a5f3c6e9b2d8a4f7c1e5b3d9a6f2c Author: Bruno Salas <[email protected]> Date: Thu Jul 31 18:22:41 2026 +0200 Añadir el botón de exportar a la barra de acciones diff --git a/index.html b/index.html ...
Con una etiqueta anotada ves dos bloques: primero la etiqueta (con su tagger, su fecha y su mensaje) y después el commit al que apunta con su diff. Con una ligera solo verías el commit, porque no hay nada más que ver.
Otras consultas útiles:
# Formato personalizado, como en git branch --format (lección 03-06)
git tag --format='%(refname:short) %(creatordate:short) %(subject)' --sort=-creatordatev1.0.1 2026-08-05 Corrección del foco tras borrar una tarea v1.0.0 2026-08-01 gestor-tareas 1.0.0 v0.9.0 2026-07-15 Version previa a la primera estable
# Qué etiquetas contienen un commit (es decir, en qué versiones entró ese cambio)
git tag --contains 7d3a8f4Esa última es de las más útiles del repertorio: responde a "¿en qué versión se corrigió esto?" sin abrir nada.
# Qué ha cambiado entre dos versiones
git log --oneline v1.0.0..v1.1.0
git diff --stat v1.0.0 v1.1.0Las etiquetas funcionan como cualquier otra referencia en rangos, diff, log y show. Todo lo que aprendiste en la lección 02-06 vale aquí.
- Etiquetar un commit del pasado
Es habitual darse cuenta de que hay que etiquetar algo después de haber seguido trabajando. Basta con pasar el commit:
tag v0.9.0 Tagger: Ana Ferrer <[email protected]> Date: Fri Aug 1 10:14:33 2026 +0200 Version previa a la primera estable commit 8b6d3c2...
Un detalle importante que se ve ahí: la fecha de la etiqueta es la de hoy, no la del commit. Es correcto: la etiqueta se creó hoy, aunque marque algo de hace semanas. Si por algún motivo necesitas que coincida:
Y como el commit puede indicarse con cualquier expresión de las que conoces (lección 02-06), todo esto es válido:
git tag -a v0.9.0 HEAD~5 -m "..."
git tag -a v0.9.0 main~10 -m "..."
git tag -a v0.9.0 funcionalidad/exportacion-csv -m "..."
- Versionado semántico
Etiquetar v1.0.0 no significa nada si el equipo no comparte qué quiere decir ese número. El versionado semántico (SemVer) es la convención más extendida para darle significado.
Formato: MAJOR.MINOR.PATCH
| Componente | Se incrementa cuando... | Efecto en los demás |
|---|---|---|
| MAJOR | Hay un cambio incompatible con la versión anterior | MINOR y PATCH vuelven a 0 |
| MINOR | Se añade funcionalidad compatible hacia atrás | PATCH vuelve a 0 |
| PATCH | Se corrige un fallo sin cambiar el comportamiento esperado | — |
Aplicado a la historia real de gestor-tareas:
| Versión | Qué cambió | Por qué ese número |
|---|---|---|
v0.1.0 |
Listado de tareas básico | Antes de la 1.0 no hay compromiso de estabilidad |
v0.9.0 |
Todo lo previsto, en pruebas | Sigue siendo previa |
v1.0.0 |
Primera versión estable | Se asume el compromiso de compatibilidad |
v1.0.1 |
Corregido el foco tras borrar | Solo una corrección: PATCH |
v1.1.0 |
Añadido el filtro de pendientes | Funcionalidad nueva, nada se rompe: MINOR |
v1.1.1 |
Corregido el contador con el filtro activo | PATCH |
v1.2.0 |
Añadida la exportación a CSV | MINOR |
v2.0.0 |
El formato de localStorage cambia y los datos de la 1.x no se leen |
Rompe compatibilidad: MAJOR |
Dos reglas que a menudo se pasan por alto:
- La versión
0.x.yes territorio sin garantías. Antes de la1.0.0, la convención dice explícitamente que cualquier cosa puede cambiar. Es el sitio donde estar mientras el diseño no esté asentado. - Una vez publicada, una versión no se toca jamás. Si
v1.0.0tenía un fallo, se publicav1.0.1. Nunca se reetiquetav1.0.0(apartado 8).
SemVer admite además sufijos para versiones previas y metadatos de compilación:
git tag -a v2.0.0-alpha.1 -m "Primera alfa de la versión 2"
git tag -a v2.0.0-rc.1 -m "Candidata a versión"
git tag -a v2.0.0 -m "gestor-tareas 2.0.0"En el orden de SemVer, v2.0.0-alpha.1 < v2.0.0-rc.1 < v2.0.0: los sufijos de prelanzamiento van antes que la versión final. git tag --sort=-v:refname lo entiende correctamente.
Cómo se decide qué entra en cada versión, quién la aprueba, cómo se generan las notas y cómo se automatiza la publicación son temas de proceso de equipo y de integración continua: los verás en los módulos 7 y 10. Aquí nos ocupa el mecanismo de Git.
- Enviar etiquetas al remoto
En la lección 04-05 dejamos esto abierto con una frase que sorprende a todo el mundo: git push no envía etiquetas. Ahora cerramos el tema.
El motivo es el refspec por defecto (lección 04-02): refs/heads/*:refs/heads/*. Solo cubre ramas. refs/tags/* queda fuera.
La etiqueta se ha creado en local y ahí sigue. Las tres formas de enviarla:
# 1. Una etiqueta concreta
git push origin v1.0.0
# 2. TODAS las etiquetas locales
git push origin --tags
# 3. Solo las ANOTADAS alcanzables desde lo que se envía
git push origin --follow-tags| Forma | Qué envía | Cuándo |
|---|---|---|
git push origin <etiqueta> |
Solo esa | Al publicar una versión concreta: lo más habitual |
git push origin --tags |
Todas, ligeras incluidas, apunten donde apunten | Casi nunca: arrastra tus marcadores personales |
git push origin --follow-tags |
Solo las anotadas que cuelgan de los commits enviados | El día a día |
--tags tiene un problema real: envía también pruebas-de-hoy, antes-del-rebase y cualquier marcador ligero que tengas por ahí, y una vez en el servidor son de todos. Por eso --follow-tags es casi siempre la opción correcta, y por eso conviene dejarla configurada:
A partir de ahí, un git push normal se lleva las etiquetas anotadas que correspondan y ninguna más.
Un matiz sobre --follow-tags: solo envía etiquetas anotadas y solo las que apuntan a commits que ya están o van a estar en el servidor. Es exactamente lo que quieres, y también otra razón práctica para usar siempre anotadas al publicar versiones.
Al recibir, no hay que hacer nada especial: git fetch y git pull traen las etiquetas de los commits que descargan. Si necesitas traerlas todas explícitamente:
git fetch --tags
git fetch --prune --prune-tags # además, borra en local las que ya no están en el servidor
- Borrar etiquetas y por qué no se mueven
Borrar en local:
Borrar en el remoto (misma sintaxis de borrado de ramas de 04-05):
Y ahora lo importante: ¿por qué mover una etiqueta ya publicada es una mala idea?
Técnicamente se puede. git tag -f v1.0.0 <otro-commit> la reapunta, y git push --force origin v1.0.0 la reapunta en el servidor. Pero:
- Nadie se entera. Quien ya tenía
v1.0.0descargada no la actualiza en ungit fetchnormal. Git es deliberadamente conservador con las etiquetas existentes: si el nombre ya existe en local, no lo toca. Resultado: durante meses, tuv1.0.0y la de Bruno apuntan a commits distintos, y ninguno de los dos lo sabe. - Rompe la premisa entera. Una etiqueta vale porque es estable. Una etiqueta que puede cambiar no sirve para nada: ya no puedes citarla en una incidencia, en un despliegue ni en un documento.
- Los artefactos ya publicados no cambian. Si
v1.0.0está desplegada en un cliente, mover la etiqueta no mueve el código del cliente. Solo consigue que la etiqueta mienta sobre qué se desplegó. - Es la misma violación de la regla de oro del módulo. Reescribir algo que otros ya tienen descargado no es una operación local.
Quien recibe una etiqueta movida ve esto, si la fuerza:
Y a partir de ahí puede tener dificultades para saber cuál era la buena.
Qué hacer en su lugar:
| Situación | Solución correcta |
|---|---|
| Te equivocaste de commit y aún no la has publicado | Bórrala en local y créala bien |
La publicaste hace cinco minutos y nadie ha hecho fetch |
Bórrala en local y en remoto, avisa al equipo, y créala de nuevo |
| La versión tiene un fallo | Publica v1.0.1. Nunca reetiquetes |
| Te equivocaste en el mensaje | Si es reciente y avisas, borrar y recrear. Si no, déjalo: no compensa |
En resumen: la etiqueta es un compromiso. Una vez enviada al servidor, se trata como inmutable.
- Etiquetas firmadas
Una etiqueta anotada puede llevar una firma criptográfica que demuestre quién la creó:
# Firmar con GPG
git tag -s v1.0.0 -m "gestor-tareas 1.0.0"
# Verificar
git verify-tag v1.0.0
git tag -v v1.0.0gpg: Signature made Fri Aug 1 10:00:00 2026 CEST gpg: using RSA key 4A7D2F8B... gpg: Good signature from "Ana Ferrer <[email protected]>" [ultimate]
Para qué sirve en la práctica: si alguien distribuye gestor-tareas descargando la etiqueta v1.0.0 del servidor, la firma le permite comprobar que esa versión la publicó realmente Ana y no alguien que consiguió acceso al servidor.
Solo funciona con etiquetas anotadas —una ligera no tiene dónde guardar la firma—, y requiere tener configurada una clave (user.signingkey, gpg.format, tag.gpgSign). La configuración completa, incluidas las firmas con claves SSH y la firma de commits, está en la lección 08-05: Mejores Prácticas de Seguridad. Aquí basta con saber que la opción existe y que es una razón más para usar anotadas.
git describe: nombrar cualquier commit
git describe: nombrar cualquier commitTienes un commit cualquiera, en medio del desarrollo, y quieres un nombre legible para él. git describe construye uno a partir de la etiqueta más reciente que lo alcanza:
Se lee así:
| Parte | Significado |
|---|---|
v1.1.0 |
La etiqueta anotada más reciente alcanzable desde este commit |
14 |
Hay 14 commits desde esa etiqueta hasta aquí |
g8c3e7f1 |
El commit actual es 8c3e7f1 (la g significa "git") |
Si estás exactamente sobre una etiqueta, el nombre es la etiqueta a secas:
Opciones importantes:
| Opción | Qué hace |
|---|---|
--tags |
Considera también las etiquetas ligeras |
--always |
Si no hay ninguna etiqueta, devuelve el hash abreviado en lugar de fallar |
--dirty |
Añade -dirty si el directorio de trabajo tiene cambios sin confirmar |
--abbrev=<n> |
Longitud del hash abreviado (--abbrev=0 lo omite: solo el nombre de la etiqueta) |
--match "<patrón>" |
Solo etiquetas que casen con el patrón |
--contains |
Al revés: la primera etiqueta que contiene este commit |
La combinación que se usa en la práctica para versionar compilaciones:
Ese identificador es extraordinariamente útil: se incrusta en la aplicación y, cuando alguien reporta un fallo desde una versión intermedia, sabes exactamente de qué commit hablas y si venía de un directorio sucio. Por ejemplo, en gestor-tareas:
// Este valor lo inyecta el script de compilación con la salida de:
// git describe --tags --always --dirty
const VERSION = 'v1.1.0-14-g8c3e7f1';
function pintarPie() {
const pie = document.getElementById('pie');
pie.textContent = 'gestor-tareas ' + VERSION;
}Y --contains, para la pregunta inversa:
"Ese commit está dos commits antes de v1.0.1", es decir: entró en la versión 1.0.1.
- Trabajar sobre una etiqueta
Situarse en una etiqueta te deja en detached HEAD (lección 03-02), porque una etiqueta no es una rama y no puede avanzar:
Note: switching to 'v1.0.0'. You are in 'detached HEAD' state... HEAD is now at 9f4c2e8 Añadir el botón de exportar a la barra de acciones
Eso está bien para mirar: inspeccionar el código de esa versión, ejecutarla, reproducir un fallo. Pero si vas a trabajar —por ejemplo, corregir un fallo de la 1.0 para publicar una 1.0.1— necesitas una rama:
Ahora sí: rama de mantenimiento que arranca exactamente en la versión publicada. Corriges (o traes la corrección desde main con git cherry-pick -x, lección 05-03), confirmas, etiquetas la nueva versión y la envías:
git cherry-pick -x 7d3a8f4
git tag -a v1.0.1 -m "Corrección del foco tras borrar una tarea"
git push origin mantenimiento/1.0 v1.0.1Ese es el ciclo completo de una versión de mantenimiento, y usa cuatro cosas de este módulo a la vez.
También puedes exportar el contenido de una etiqueta sin clonar nada:
git archive genera un .zip (o .tar.gz) con el árbol de esa etiqueta, sin el directorio .git. Es la forma canónica de producir el paquete de una versión.
Errores Comunes y Consejos
Error 1: crear etiquetas ligeras para versiones. git tag v1.0.0 sin -a no guarda quién, ni cuándo, ni por qué, no se puede firmar y --follow-tags no la envía. Para versiones, siempre -a.
Error 2: creer que git push envía las etiquetas. No lo hace. Es la sorpresa clásica: creas v1.0.0, haces push, y en el servidor no está. git push origin v1.0.0 o push.followTags true.
Error 3: usar --tags por costumbre. Envía todas tus etiquetas locales, incluidos los marcadores de pruebas. Una vez en el servidor, limpiarlas es engorroso y hay que avisar a todo el mundo.
Error 4: mover una etiqueta publicada. Quien ya la tenía no la actualiza y acabáis con dos verdades distintas. Si hay un fallo, se publica la siguiente versión.
Error 5: confiar en el orden alfabético. v1.10.0 va antes que v1.2.0 en orden alfabético. Configura tag.sort -v:refname.
Error 6: usar el mismo nombre para una rama y una etiqueta. Genera ambigüedades en checkout, switch y push que después cuesta entender.
Error 7: esperar que git describe vea las ligeras. Por defecto solo mira las anotadas. Si tu repositorio solo tiene ligeras, git describe falla con no names found; ahí hace falta --tags.
Consejo 1: etiqueta desde main y solo lo que se publica. Una etiqueta por versión real. Etiquetar commits intermedios "por si acaso" llena el espacio de nombres de ruido permanente.
Consejo 2: escribe un mensaje de verdad. El mensaje de la etiqueta es el mejor sitio para las notas de la versión: viaja con el repositorio, no depende de ninguna herramienta externa y se lee con git show.
Consejo 3: incrusta git describe --tags --always --dirty en tus compilaciones. Es la forma más barata de que cualquier informe de error incluya la versión exacta.
Consejo 4: git tag --contains <sha> para responder "¿en qué versión entró esto?". Es más rápido y más fiable que buscar en el log por fechas.
Consejo 5: acuerda SemVer con el equipo y escríbelo. El valor de MAJOR.MINOR.PATCH está en que todos entiendan lo mismo. Un número de versión que nadie sabe interpretar es solo un número.
Ejercicios
Ejercicio 1: ligera frente a anotada, con las manos
En un repositorio de pruebas con al menos tres commits:
- Crea una etiqueta ligera y una anotada sobre el mismo commit.
- Demuestra con
git cat-file -tque una resuelve acommity la otra atag. - Muestra el contenido del objeto
tagcongit cat-file -pe identifica sus cinco partes. - Compara la salida de
git showcon cada una.
Ejercicio 2: una historia de versiones
Simula la evolución de gestor-tareas:
- Tres commits y
v1.0.0(anotada, con mensaje de notas de versión). - Un commit de corrección y
v1.0.1. - Dos commits de funcionalidad nueva y
v1.1.0. - Lista las etiquetas ordenadas por versión, de la más nueva a la más antigua.
- Muestra qué cambió entre
v1.0.0yv1.1.0. - Averigua en qué versión entró el commit de corrección sin mirar el log.
Ejercicio 3: git describe y una rama de mantenimiento
Partiendo del ejercicio 2:
- Añade cuatro commits más a
mainy comprueba la salida degit describe. Interpreta cada parte. - Modifica un fichero sin confirmar y observa el efecto de
--dirty. - Crea una rama de mantenimiento que arranque en
v1.0.0. - Lleva a esa rama, con cherry-pick, la corrección de la 1.0.1, y etiqueta el resultado como
v1.0.2. - Comprueba con
git describeen cada rama que los nombres son coherentes.
Soluciones
Solución 1:
mkdir /tmp/practica-tags && cd /tmp/practica-tags
git init -b main
echo "uno" > f.txt && git add . && git commit -m "Primero"
echo "dos" >> f.txt && git commit -am "Segundo"
echo "tres" >> f.txt && git commit -am "Tercero"
# 1. Las dos etiquetas
git tag ligera
git tag -a anotada -m "Esta es anotada"object 6d3f2a9c8b1e5f7d4a2c9e6b3f8d1a5c7e4b2f9d type commit tag anotada tagger Carla Vidal <[email protected]> 1754035200 +0200 Esta es anotada
Las cinco partes: object (el commit apuntado), type (qué es), tag (el nombre), tagger (autoría y fecha) y el mensaje.
commit 6d3f2a9... Author: Carla Vidal <[email protected]> Date: Sat Aug 1 11:02:14 2026 +0200
tag anotada Tagger: Carla Vidal <[email protected]> Date: Sat Aug 1 11:03:40 2026 +0200 Esta es anotada commit 6d3f2a9...
La anotada muestra un bloque más: el suyo propio.
Solución 2:
mkdir /tmp/practica-versiones && cd /tmp/practica-versiones
git init -b main
echo "<h1>Gestor de tareas</h1>" > index.html && git add . && git commit -m "Estructura inicial"
echo "body { font-family: sans-serif; }" > estilos.css && git add . && git commit -m "Añadir estilos base"
echo "const tareas = [];" > app.js && git add . && git commit -m "Añadir el listado de tareas"
git tag -a v1.0.0 -m "gestor-tareas 1.0.0
Primera versión estable: listado de tareas con estilos base."echo "// foco tras borrar" >> app.js && git commit -am "Devolver el foco al campo tras borrar"
git tag -a v1.0.1 -m "Corrección del foco tras borrar una tarea"
echo "// filtro" >> app.js && git commit -am "Añadir el filtro de pendientes"
echo ".filtro { margin: 1rem; }" >> estilos.css && git commit -am "Añadir estilos del filtro"
git tag -a v1.1.0 -m "gestor-tareas 1.1.0
Nuevo filtro de tareas pendientes."v1.1.0 gestor-tareas 1.1.0 v1.0.1 Corrección del foco tras borrar una tarea v1.0.0 gestor-tareas 1.0.0
2c9f4e7 Añadir estilos del filtro 8b1d6a3 Añadir el filtro de pendientes 5f7c2e9 Devolver el foco al campo tras borrar
Entró en la v1.0.1 (la primera de la lista) y, naturalmente, sigue presente en la v1.1.0.
Solución 3:
# 1. Cuatro commits más y describe
for i in 1 2 3 4; do echo "// cambio $i" >> app.js; git commit -am "Cambio $i"; done
git describeLa etiqueta anotada más reciente alcanzable es v1.1.0, han pasado 4 commits desde ella, y el commit actual es 9e2c6b1.
# 3 y 4. Rama de mantenimiento y cherry-pick
git switch -c mantenimiento/1.0 v1.0.0
git log --oneline -1Cada rama se nombra respecto a su propia línea de etiquetas, que es exactamente lo que se espera de un esquema de versiones con mantenimiento.
Conclusión
Las etiquetas son la memoria estable del repositorio. Lo esencial:
- Una etiqueta es una referencia que no se mueve. Vive en
refs/tags/, marca un commit concreto para siempre y no puede ser el destino deHEAD(te deja en detached HEAD). - Hay dos clases. La ligera es un puntero pelado, sin objeto propio. La anotada crea un objeto
tagen la base de datos —el cuarto tipo de la lección 01-04— con autor, fecha, mensaje y firma opcional. Para versiones publicadas, siempre anotadas. - Se crean con
git tag -a <nombre> -m "...", opcionalmente sobre un commit del pasado; se listan congit tag -l "<patrón>",-ny--sort=-v:refname; se examinan congit show; ygit tag --contains <sha>responde a "¿en qué versión entró esto?". - El versionado semántico (
MAJOR.MINOR.PATCH) da significado compartido al número: incompatible / funcionalidad nueva / corrección. Antes de la1.0.0no hay compromiso; después, una versión publicada no se toca nunca. - Las etiquetas no viajan solas:
git push origin <etiqueta>para una concreta,--tagspara todas (rara vez lo que quieres) y--follow-tags—opush.followTags true— para las anotadas alcanzables, que es lo correcto en el día a día. - Se borran con
git tag -den local ygit push origin --deleteen remoto, pero una etiqueta publicada no se mueve: quien ya la tiene no la actualiza, y el resultado son dos verdades distintas conviviendo. Si hay un fallo, se publica la siguiente versión. git describe --tags --always --dirtynombra cualquier commit respecto a la última etiqueta y es la forma canónica de versionar compilaciones.- Para trabajar sobre una versión publicada, crea una rama desde la etiqueta; la etiqueta sola solo sirve para mirar.
Lo que viene
Ya sabemos marcar el pasado. Falta la operación complementaria y la más delicada de todas: deshacerlo.
Porque va a pasar. Alguien va a publicar en main un commit que rompe algo, y va a estar ya en el servidor, y tres personas lo van a tener descargado. La regla de oro prohíbe reescribirlo. ¿Entonces?
Git tiene una respuesta para eso, y es elegante: no borrar el commit, sino añadir otro que aplique el cambio contrario. Es git revert, la única forma segura de deshacer algo que ya es público, y con ella cerramos el módulo en la lección 05-06: Revirtiendo Confirmaciones.
Dominando Git: De Principiante a Avanzado
Módulo 1: Introducción a Git
- ¿Qué es Git?
- Instalando Git
- Terminología Básica de Git
- El Modelo de Datos de Git
- Configurando Git
- Configuración Inicial
Módulo 2: Operaciones Básicas de Git
- Creando un Repositorio
- Clonando un Repositorio
- Flujo de Trabajo Básico de Git
- Preparando y Confirmando Cambios
- Inspeccionando Cambios con git diff
- Visualizando el Historial de Confirmaciones
Módulo 3: Ramas y Fusión
- Entendiendo las Ramas
- Creando y Cambiando Ramas
- Fusionando Ramas
- Estrategias de Fusión
- Resolviendo Conflictos de Fusión
- Gestión de Ramas
Módulo 4: Trabajando con Repositorios Remotos
- Entendiendo los Repositorios Remotos
- Agregando un Repositorio Remoto
- Autenticación con Repositorios Remotos
- Obteniendo y Extrayendo Cambios
- Enviando Cambios
- Rastreando Ramas
Módulo 5: Operaciones Avanzadas de Git
- Rebase
- Rebase Interactivo
- Cherry-Picking de Confirmaciones
- Guardando Cambios Temporales
- Etiquetando Confirmaciones
- Revirtiendo Confirmaciones
Módulo 6: Herramientas y Técnicas de Git
- Usando Git Hooks
- Git Bisect
- Git Blame
- Git Log y Alias
- Submódulos de Git
- Múltiples Copias de Trabajo con git worktree
Módulo 7: Estrategias de Colaboración y Flujo de Trabajo
- Forks y Pull Requests
- Revisiones de Código con Git
- Flujo de Trabajo Git Flow
- GitHub Flow
- Trunk Based Development
- Integración Continua con Git
Módulo 8: Mejores Prácticas y Consejos de Git
- Escribiendo Buenos Mensajes de Confirmación
- Manteniendo un Historial Limpio
- Ignorando Archivos con .gitignore
- Atributos de Fichero con .gitattributes
- Mejores Prácticas de Seguridad
- Consejos de Rendimiento
Módulo 9: Solución de Problemas y Depuración
- Problemas Comunes de Git
- Deshaciendo Cambios
- Resolviendo Divergencias con el Remoto
- Recuperando Confirmaciones Perdidas
- Tratando con Repositorios Corruptos
- Técnicas Avanzadas de Depuración
