Detached HEAD en Git: qué es y cómo salir
Ves 'You are in detached HEAD state' y cunde el pánico. Te explico qué es HEAD, cómo acabas en detached HEAD y cómo sales sin perder tu trabajo.
Querías ver cómo estaba el código hace tres commits, hiciste git checkout de un hash, y Git te soltó un párrafo entero de advertencia sobre “detached HEAD”. El corazón te dio un vuelco. Tranquilo: no has roto nada. Aquí explico qué es HEAD, por qué acabas en detached HEAD git y, sobre todo, cómo sales sin perder tu trabajo.
¿Qué es HEAD en Git?
HEAD es un puntero que marca dónde estás ahora mismo en el repositorio. Cuando haces un commit, el nuevo commit se cuelga justo de donde apunta HEAD.
Lo importante es entender que HEAD casi nunca apunta directamente a un commit. Apunta a una rama, y la rama apunta al último commit de esa línea de trabajo. Es una cadena de dos saltos:
HEAD ---> main ---> a1b2c3d (último commit)
Cuando estás en main y haces un commit nuevo, la rama main avanza al commit recién creado y HEAD sigue apuntando a main. Por eso el trabajo se queda “pegado” a la rama sin que tengas que hacer nada: HEAD empuja a la rama, y la rama guarda el sitio.
¿Qué significa “detached HEAD”?
Estás en detached HEAD cuando HEAD apunta directamente a un commit concreto en lugar de a una rama. Se salta el paso intermedio:
HEAD ---> a1b2c3d (commit suelto, sin rama de por medio)
La palabra “detached” es literal: HEAD está desacoplado de cualquier rama. Sigues teniendo todo el repositorio delante, puedes leer archivos, compilar, ejecutar tests y hasta hacer commits. La diferencia es que esos commits nuevos no los guarda ninguna rama. Se cuelgan de HEAD y de nada más.
El mensaje que ves es este, y dice exactamente lo que pasa:
$ git checkout a1b2c3d
Note: switching to 'a1b2c3d'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at a1b2c3d Fix login redirect
Git no te está regañando. Te está explicando la única regla que importa: los commits que hagas aquí se pierden si te vas sin crear una rama primero.
¿Cómo acabas en detached HEAD?
Acabas en detached HEAD siempre que le pides a Git ir a un punto que no es una rama local. Los casos más comunes:
- Checkout de un hash de commit:
git checkout a1b2c3dpara inspeccionar el pasado. - Checkout de un tag:
git checkout v1.4.0. Un tag apunta a un commit fijo, no a una rama que avanza. - Checkout de una rama remota directamente:
git checkout origin/main. Eso es la referencia remota, no tu rama localmain. git bisect: mientras buscas el commit que introdujo un bug, Git te va moviendo por commits sueltos en detached HEAD.- Submódulos: un submódulo siempre se registra en un commit exacto, así que dentro de él vives en detached HEAD por diseño.
En todos estos casos el patrón es el mismo. Le has pedido a Git “ponme en este commit”, no “ponme en esta rama”. Y Git hace justo eso.
Cargando ejercicio...
¿Es peligroso? ¿He perdido algo?
No has perdido nada y no es peligroso mirar. Entrar en detached HEAD es una operación de solo lectura desde el punto de vista de tus ramas: main y el resto siguen intactas, apuntando exactamente a donde estaban. Puedes navegar por el historial con total tranquilidad.
El único riesgo real aparece cuando haces commits nuevos en detached HEAD y luego te cambias a otra rama sin guardarlos. Como ninguna rama apunta a esos commits, dejan de ser accesibles por su nombre. No se borran al instante, pero quedan huérfanos, y Git deja de mostrártelos en el log normal. Más abajo te enseño a rescatarlos, así que ni en ese caso hay drama.
Aquí conviene tener claro el modelo de dos estados:
| Situación | HEAD adjunto (en una rama) | HEAD desacoplado (detached) |
|---|---|---|
| A qué apunta HEAD | A una rama (main), y la rama al commit | Directamente a un commit (a1b2c3d) |
Al hacer git commit | La rama avanza y guarda el commit | El commit se cuelga solo de HEAD |
| Al cambiar de rama | No pierdes nada, la rama recuerda el sitio | Los commits nuevos quedan huérfanos si no creaste rama |
| Cómo se recupera | No hace falta, es el estado normal | git switch -c antes, o git reflog después |
¿Cómo salgo si no hice cambios?
Si solo estabas mirando y no hiciste commits, salir es una línea:
# Vuelve a la rama en la que estabas antes del checkout
git switch -
El guion - significa “la referencia anterior”, igual que cd - en la terminal te devuelve al directorio previo. Si prefieres nombrar la rama a la que quieres ir, también vale:
git switch main
Con eso HEAD vuelve a apuntar a una rama y desapareces del estado detached. No queda nada que limpiar y no has roto nada.
Un apunte sobre comandos: git switch es la forma moderna y recomendada de moverte entre ramas, y desde hace varias versiones es un comando estable de Git. git checkout sigue funcionando, pero hace demasiadas cosas distintas (cambiar de rama, restaurar archivos, entrar en detached HEAD), y esa sobrecarga es justo la que confunde. Cuando el objetivo es moverte, usa switch.
¿Cómo conservo el trabajo que hice en detached HEAD?
Si hiciste commits que quieres conservar, crea una rama antes de salir. Ese es el momento clave:
# Estás en detached HEAD con commits que quieres guardar
git switch -c experimento-login
git switch -c experimento-login crea una rama nueva justo donde está HEAD ahora mismo y te lleva a ella. Tus commits sueltos pasan a colgar de experimento-login y ya tienen dueño. A partir de ahí es una rama normal: puedes seguir trabajando, hacer push, o integrarla a tu rama principal con un merge o un rebase.
El flujo mental es sencillo. Antes de dejar el estado detached, pregúntate: ¿he hecho commits aquí que quiero conservar? Si la respuesta es sí, git switch -c <nombre> primero. Si es no, git switch - y listo. Si quieres profundizar en cómo se crean y manejan las ramas, lo cubro en detalle en crear y cambiar ramas en Git.
¿Y si ya cambié de rama y “perdí” los commits?
No los has perdido de verdad. Git guarda un registro local de todos los sitios donde HEAD ha estado, y ahí siguen tus commits huérfanos. Ese registro es el reflog:
git reflog
Verás algo así:
9f8e7d6 HEAD@{0}: checkout: moving from a1b2c3d to main
4d5e6f7 HEAD@{1}: commit: Prueba de nuevo login
a1b2c3d HEAD@{2}: checkout: moving from main to a1b2c3d
La línea commit: Prueba de nuevo login con hash 4d5e6f7 es el trabajo que creías perdido. Cópialo y clávale una rama encima:
git branch rescate 4d5e6f7
Ahora rescate apunta a ese commit y vuelve a ser accesible desde el log normal. Puedes hacerle git switch rescate y seguir. El reflog es tu red de seguridad para casi cualquier “he perdido un commit” en Git, no solo para detached HEAD. Para el panorama completo de recuperación, mira la guía para deshacer cambios en Git.
Errores comunes
Cambiar de rama sin crear una primero
Es el fallo clásico: haces tres commits buenos en detached HEAD, ejecutas git switch main y ves el aviso de que dejas commits atrás. El pánico es innecesario porque el reflog los conserva, pero te ahorras el susto creando la rama antes de irte. Si Git te avisa al cambiar, léelo: casi siempre te da el hash exacto que necesitas.
Tratar detached HEAD como un error a martillazos
Detached HEAD no es un error, así que no lo “arregles” con un git reset --hard a ciegas. Ese comando descarta cambios de trabajo de verdad y puede convertir un susto inofensivo en una pérdida real. La salida correcta es git switch; el git reset --hard a ciegas solo empeora el susto.
Confundir checkout de rama con checkout de commit
git checkout main te deja en una rama (HEAD adjunto). git checkout a1b2c3d te deja en un commit suelto (detached HEAD). El comando es el mismo, pero el resultado depende de si lo que le pasas es un nombre de rama o un identificador de commit. Por eso git switch separó ambas ideas: git switch main para ramas, git switch --detach a1b2c3d cuando de verdad quieres desacoplar a propósito.
Creer que los commits huérfanos se borran al instante
Cuando abandonas commits en detached HEAD no desaparecen de golpe. Se quedan alcanzables por el reflog durante bastante tiempo antes de que la recolección de basura (git gc) los limpie. Tienes margen de sobra para rescatarlos, pero no lo dejes semanas: no cuentes con que estarán ahí para siempre.
Checklist para no temer a detached HEAD
- Sé que HEAD normalmente apunta a una rama, y la rama a un commit
- Reconozco que un checkout de hash, tag o
origin/algome deja en detached HEAD - Si solo miraba, salgo con
git switch - - Si hice commits que quiero conservar, creo la rama con
git switch -c <nombre>antes de irme - Si creo que perdí commits, uso
git reflogpara encontrar el hash ygit branch <nombre> <hash>para rescatarlos - No uso
git reset --hardcomo reacción al pánico
Practica Git sin miedo a romper nada
Leer sobre detached HEAD ayuda, pero el miedo se quita practicando en un sitio donde equivocarte no cuesta nada. En el curso Git de cero a profesional haces exactamente esto: entras y sales de detached HEAD, rescatas commits con el reflog y montas tu modelo mental de HEAD y ramas con ejercicios interactivos, sin tocar tu repo real.
Un concepto nuevo cada semana
Preguntas Frecuentes
¿Detached HEAD borra mi trabajo?
No. Entrar en detached HEAD no toca ninguna de tus ramas: siguen apuntando exactamente a donde estaban. El único caso en el que puedes perder acceso a algo es si haces commits nuevos en detached HEAD y luego cambias de rama sin crear una rama para ellos, y aun así el reflog los conserva un tiempo.
¿Cómo vuelvo rápido a mi rama desde detached HEAD git?
Ejecuta git switch - y vuelves a la rama en la que estabas antes del checkout. Si prefieres ir a una rama concreta, usa git switch main (o el nombre que sea). En cuanto HEAD apunta de nuevo a una rama, sales del estado detached.
¿Puedo hacer commits en detached HEAD?
Sí, puedes hacer todos los commits que quieras. El problema no es hacerlos, es irte sin guardarlos. Antes de cambiar a otra rama, crea una rama con git switch -c <nombre> para que esos commits tengan dueño y no queden huérfanos.
¿Qué es git reflog y cómo me salva en detached HEAD?
El reflog es un registro local de todos los sitios por los que ha pasado HEAD, incluidos los commits que dejaste en detached HEAD. Ejecuta git reflog, localiza el hash de tu commit y créale una rama con git branch <nombre> <hash>. Es la red de seguridad que hace que casi nada se pierda de verdad en Git.
¿git checkout y git switch hacen lo mismo?
Para moverte entre ramas, sí, pero git switch es más claro. git checkout está sobrecargado: cambia de rama, restaura archivos y entra en detached HEAD, todo con el mismo nombre. git switch separa esas tareas y es la forma moderna recomendada de cambiar de rama. Para navegar al pasado con seguridad, te lo cuento en volver a un commit anterior en Git.