Javier Valencia Javier Valencia
Terminal con los comandos git stash, git tag y git fetch

Git intermedio III: stash, tags y fetch

Javier Valencia · · 4 min de lectura · 4 visitas · Desarrollo
git desarrollo terminal herramientas productividad git-intermedio

Tercera entrega de la serie Git intermedio. Las anteriores: ramas y deshacer con cabeza. Tiempo de lectura estimado: 5 minutos.

Para cerrar el nivel intermedio, tres comandos que resuelven situaciones muy concretas pero frecuentes: guardar trabajo en curso cuando algo urgente te interrumpe (git stash), marcar un punto importante de la historia (git tag) y mirar el estado del remoto sin traerte nada (git fetch). No son glamurosos, pero hacen el día a día más tranquilo.

git stash: guardar trabajo a medias

El escenario: estás en medio de algo, con cambios en el working tree que aún no quieres commitear, y alguien te pide una revisión urgente en otra rama. No quieres hacer un commit a medias solo para cambiar de rama. git stash es el comando.

git stash                    # guarda cambios y vuelve a HEAD limpio
git stash push -m "WIP login"  # igual, con mensaje descriptivo
git stash list               # lista los stashes guardados
git stash pop                # restaura el último stash y lo borra
git stash apply              # restaura sin borrar el stash
git stash drop               # borra un stash
git stash show -p stash@{1}  # diff del stash

Flujo típico:

git stash -m "Formulario login a medias"
git switch rama-urgente
# ... hago el fix, commit, push, revisión, merge ...
git switch -
git stash pop

Detalles importantes:

  • Por defecto, git stash no stashea ficheros untracked. Si tienes ficheros nuevos sin git add, no entran. Flag: git stash -u (untracked).
  • Los conflictos en pop son reales. Si has cambiado cosas que chocan con lo stasheado, al hacer pop te aparecen conflictos como en un merge. Resuelves, git add, y el stash ya está aplicado (se puede borrar con git stash drop si usaste apply, o se borró solo si usaste pop).
  • Stash es local: no sale de tu máquina, nadie más lo ve. No es para colaborar.

Mi recomendación: usa stash para interrupciones cortas, no como "almacén de trabajo". Si algo va a vivir más de un día, hazlo commit en una rama; los stashes se olvidan fácilmente y cuando acumulas quince te pierdes.

Variante muy útil:

git stash --keep-index

Stashea solo lo que no está en el index. Útil para el flujo: "hago add de lo que voy a commitear, stasheo el resto, corro tests con solo lo stageado, commiteo si pasan".

git tag: marcar puntos importantes

Los tags son punteros a commits, igual que las ramas, pero con una diferencia clave: no se mueven. Una rama avanza con cada commit nuevo; un tag se queda donde estaba. Se usan típicamente para marcar versiones: v1.0.0, v1.2.3, release-2026-04.

Hay dos tipos:

git tag v1.0.0                       # lightweight tag
git tag -a v1.0.0 -m "Release 1.0"   # annotated tag

Los annotated guardan autor, fecha, mensaje y firma opcional. Los lightweight son solo un puntero con un nombre. Para releases públicas se usan annotated; para tags locales rápidos, lightweight.

Operaciones básicas:

git tag                      # lista todos los tags
git tag -l "v1.*"            # lista con patrón
git tag -a v1.2.0 abc123     # etiqueta un commit concreto
git tag -d v1.0.0            # borra un tag local
git push origin v1.0.0       # pushea UN tag
git push origin --tags       # pushea todos los tags
git push origin :refs/tags/v1.0.0   # borra un tag en el remoto

Los tags no se pushean con git push normal. Por defecto git no los sube. Tienes que hacerlo explícitamente. Esto evita subir tags de prueba por error, pero también hace que mucha gente se olvide. Si haces release, acuérdate.

Ver qué hay en un tag:

git show v1.0.0

Te enseña el mensaje del tag (si es annotated), el commit que apunta y el diff de ese commit.

Los tags se usan también en workflows de CI/CD: "cuando aparezca un tag v*, dispara un deploy". Por eso importa que el nombre sea semánticamente significativo: semver (vMAJOR.MINOR.PATCH) es lo más común.

Cosas que no hacer: mover o reescribir un tag ya publicado. Es posible con -f, pero rompe la confianza: otra persona que tenga el tag viejo verá que ahora apunta a otro commit. Si una release se rompió, haz una nueva (v1.0.1), no sobreescribas v1.0.0.

git fetch: mirar sin tocar

git fetch trae datos del remoto a tu repo, pero no los mezcla con tu trabajo. Actualiza las referencias remotas (origin/main, origin/feature-x) pero tu working tree y tus ramas locales siguen como estaban.

git fetch                    # fetch de origin
git fetch origin             # igual, explícito
git fetch --all              # fetch de todos los remotos
git fetch --prune            # fetch + borra referencias a ramas remotas ya borradas
git fetch origin main        # solo la rama main de origin

¿Para qué sirve sin merge? Mucho más de lo que parece:

Ver qué han subido los demás sin mezclarlo. Tras git fetch, puedes mirar git log origin/main para ver los commits nuevos que aún no tienes, o git diff main origin/main para ver el diff. Si no te convence, no mergeas.

Saber si tu rama está atrasada. git status después de un fetch te dice "tu rama está N commits detrás de origin/main". Sin fetch no sabe.

Preparar un rebase o un merge deliberado. Yo prefiero git fetch + decisión manual a git pull ciego. Especialmente en ramas compartidas o en main.

--prune es clave. Con el tiempo acumulas referencias a ramas remotas (origin/fix-algo, origin/feature-blabla) que ya se borraron del servidor tras mergear PRs. --prune las limpia. Se puede hacer por defecto:

git config --global fetch.prune true

Y ya todos tus fetches limpian basura vieja automáticamente.

Combinaciones del día a día

Revisar el repo después de volver de vacaciones:

git fetch --all --prune
git log --oneline --all --graph -20

Ves todo lo que ha pasado mientras no estabas, sin tocar nada.

Hacer un hotfix sin perder lo que tenías a medias:

git stash -m "Feature a medias"
git switch main
git pull --rebase
git switch -c hotfix/algo-urgente
# ... fix ...
git commit -am "Fix: validación de email"
git push -u origin hotfix/algo-urgente
git switch -
git stash pop

Marcar una release y subirla:

git switch main
git pull --rebase
git tag -a v2.0.0 -m "Release 2.0.0: migración a Go 1.24"
git push origin v2.0.0

Errores típicos

Olvidar git stash pop y seguir trabajando. Si stasheas y te cambias de contexto, al volver verás el working tree limpio y pensarás que no tenías nada. git stash list de vez en cuando evita sorpresas.

No pushear los tags. "El tag no sale en el release"... porque no hiciste git push origin v1.0.0. Configurable con git config --global push.followTags true para que acompañen a los commits.

Usar git pull en vez de git fetch cuando solo querías mirar. pull implica merge (o rebase). Si no quieres integrar todavía, solo ver, usa fetch.

Hasta aquí el intermedio

Con los nueve comandos de la serie intermedia (branch, switch, merge, restore, reset, revert, stash, tag, fetch) cubres todo lo que suele aparecer en un día de trabajo en equipo sin sobresaltos. Lo que queda son los comandos que usas menos pero que sacan las castañas del fuego cuando algo se tuerce: rebase para reescribir historia limpia, bisect para encontrar el commit que rompió algo, worktree para tener varias ramas checked out a la vez.

De todo eso va la serie avanzada, que empieza en la próxima entrega con git rebase, git cherry-pick y git commit --amend. Si quieres repasar el nivel básico antes, sigue aquí: Git básico.