detached-head-en-git

Entendiendo el estado Detached HEAD en Git

  • 6 min

El estado Detached HEAD es una situación donde HEAD apunta directamente hacia un commit en lugar de referenciar una rama.

En artículos anteriores vimos cómo restaurar un archivo específico (git restore). Pero a veces, la necesidad no es recuperar un fichero suelto, sino llevar todo el proyecto a un estado anterior.

Quizás necesitas compilar la versión exacta que entregaste al cliente hace seis meses para reproducir un bug. O quieres verificar si una funcionalidad existía en el commit a1b2c3d.

Para esto, necesitamos mover el puntero HEAD. Al hacerlo de forma directa, entraremos en un estado técnico conocido como Detached HEAD.

¿Qué significa esto a nivel de arquitectura interna? Básicamente que si no tienes cuidado puedes liarla parda 👇.

El comando para viajar al pasado

Para mover nuestro entorno de trabajo completo a un commit específico, usamos el comando switch con la bandera --detach:

git switch --detach a1b2c3d`
Copied!

Antiguamente se usaba git checkout a1b2c3d

Al ejecutar esto, Git actualiza tu Working Directory para que coincida exactamente con la foto guardada en ese commit.

Inmediatamente, Git mostrará un aviso extenso que comienza con:

You are in ‘detached HEAD’ state.

Empieza la fiesta 🚨.

Anatomía del Detached HEAD

Técnicamente, “Detached HEAD” significa simplemente: HEAD está apuntando directamente a un Commit, no a una Rama.

Para comprender este estado, debemos recordar cómo funciona el puntero HEAD en condiciones normales.

Estado Normal (Attached): Generalmente, HEAD apunta a una Rama. Cuando haces un nuevo commit, Git sabe que debe actualizar la referencia de main para que avance.

Estado Detached: Cuando HEAD apunta directamente a un commit, saltándose la referencia de rama.

¿Qué puedo (y no) hacer aquí?

Este es un estado de observación. Es seguro para:

  • Compilar y ejecutar el proyecto en esa versión antigua.
  • Ejecutar tests.
  • Inspeccionar archivos.

El problema surge si decides escribir código y hacer commits en este estado.

El peligro de los commits huérfanos

Supongamos que estando en Detached HEAD arreglas un bug y haces git commit. Git creará un nuevo commit D y moverá el HEAD a él.

Hasta aquí todo parece bien. El problema ocurre cuando decides volver al presente:

git switch main
Copied!

En el momento en que cambias a main:

HEAD deja de apuntar a D y vuelve a apuntar a main.

Ninguna rama apunta a D.

El commit D se queda huérfano e inaccesible. No aparecerá en el git log y, eventualmente, el recolector de basura de Git lo eliminará definitivamente.

Cómo “arreglar” un Detached HEAD

Hay dos escenarios posibles al trabajar en este estado:

Escenario A: Solo estaba mirando

Si solo has entrado para mirar y no has hecho cambios, realmente no hay nada que arreglar. Simplemente vuelve a tu rama habitual:

git switch main
Copied!

Escenario B: He hecho commits y quiero guardarlos

Si has generado commits en estado Detached HEAD (por error o intencionadamente para probar un fix) y quieres conservarlos, debes crear una rama que apunte a ellos antes de irte.

Estando todavía en el estado Detached HEAD (sobre tu nuevo commit D), ejecuta:

git switch -c fix-antiguo
Copied!

¿Qué ocurre internamente?

  1. Git crea una nueva etiqueta de rama llamada fix-antiguo pegada a tu commit actual (D).
  2. Git reconecta HEAD a esta nueva rama.

Has convertido tus commits temporales en una línea de historia. Ahora puedes fusionar esa rama con main o seguir trabajando en ella con total seguridad.