Guía

git checkout, switch y restore: cuándo usar cada uno

Actualizado: · Skillaria.Top

git checkout hace dos cosas distintas: cambiar de rama y restaurar archivos, por eso desde Git 2.23 sus tareas se repartieron entre git switch (ramas) y git restore (archivos). Para cambiar de rama usa git switch nombre, para descartar cambios sin confirmar en un archivo usa git restore archivo, y deja checkout para scripts antiguos y costumbres arraigadas.

Por qué git checkout tiene dos funciones

git checkout hace, por motivos históricos, dos operaciones completamente distintas. Con un nombre de rama mueve HEAD y actualiza la carpeta de trabajo. Con una ruta de archivo toma la versión del archivo del índice o de un commit y sobrescribe tus cambios sin avisar. El mismo comando unas veces cambia de rama de forma segura y otras descarta trabajo sin guardar de manera irreversible.

Por eso Git 2.23 introdujo dos comandos separados: git switch para ramas y git restore para archivos. Nadie ha eliminado checkout, sigue funcionando perfectamente, pero el código nuevo, la documentación y las propias sugerencias de Git usan switch y restore. Si estás aprendiendo, empieza por ellos; aun así conviene conocer checkout, porque aparece en tutoriales, scripts y entrevistas de trabajo.

Equivalencias entre comandos

Tareagit checkoutComando nuevo
Cambiar a una ramagit checkout maingit switch main
Crear una rama y cambiar a ellagit checkout -b featuregit switch -c feature
Crear o reiniciar una ramagit checkout -B featuregit switch -C feature
Volver a la rama anteriorgit checkout -git switch -
Ir a un commit (detached HEAD)git checkout 3f2a1c9git switch --detach 3f2a1c9
Descartar cambios en un archivogit checkout -- app.jsgit restore app.js
Quitar un archivo del índicegit reset HEAD app.jsgit restore --staged app.js
Traer un archivo de otra rama o commitgit checkout main -- app.jsgit restore --source=main --staged --worktree app.js
Descartar todos los cambios de la carpetagit checkout -- .git restore .

Fíjate en el -- de los comandos checkout. Es un separador que significa «a partir de aquí van rutas». Evita ambigüedades cuando un archivo y una rama se llaman igual. Restore no tiene ese problema, porque solo trabaja con archivos.

git checkout para ramas

git checkout feature/login        # cambiar de rama
git checkout -b feature/login     # crear desde el commit actual y cambiar
git checkout -b hotfix origin/main   # crear a partir de una rama remota
git checkout -t origin/feature/x  # rama local que sigue a la remota

Si no existe la rama local pero en el servidor hay una rama con ese nombre, git checkout feature/x (igual que git switch feature/x) crea la rama local y configura el seguimiento automáticamente. Antes hace falta un git fetch; de lo contrario Git no sabe que existe la nueva rama remota.

Cambiar de rama no pierde los cambios sin confirmar: se trasladan a la otra rama si no entran en conflicto con ella. Si hay conflicto, Git se niega y te propone hacer commit o guardar los cambios con git stash. La opción -f (--force) cambia de rama descartando las modificaciones locales, y eso ya es una operación peligrosa.

git switch: solo ramas

Switch reproduce la parte de checkout relacionada con ramas, pero con reglas más estrictas. La diferencia principal: no salta a un commit o a una etiqueta sin un --detach explícito. El comando git switch v1.0 devuelve un error en lugar de pasar sin avisar a detached HEAD, así que es más difícil acabar «fuera de una rama» por accidente.

git switch main
git switch -c feature/cart
git switch -c feature/cart origin/main
git switch --detach v1.0
git switch -              # rama anterior
git switch -m main        # llevar los cambios con una fusión a tres bandas

git restore: el botón de deshacer para archivos

Restore devuelve los archivos a un estado guardado y no toca en absoluto el historial de commits. Para usarlo con seguridad hay que tener presentes las tres áreas de Git: la carpeta de trabajo (lo que ves en el editor), el índice o staging area (lo preparado con git add) y los commits.

Cómo descartar cambios en un archivo antes de git add

git restore app.js         # recuperar la versión del índice
git restore src/           # todos los archivos de la carpeta
git restore .              # todos los archivos modificados del proyecto

Sin opciones, restore restaura la carpeta de trabajo a partir del índice. Si el archivo no se añadió al índice después del último commit, equivale a la versión del último commit. Los cambios desaparecen sin dejar rastro, no van a ninguna papelera, así que antes de git restore . echa un vistazo a git diff.

Cómo quitar un archivo del staging después de git add

git restore --staged app.js

El archivo deja de estar preparado para el commit, pero tus cambios en él se conservan. Es la forma más segura de restore: no se pierde nada. Es justo el comando que sugiere git status en la sección «Changes to be committed».

Cómo deshacerlo todo: en el índice y en el archivo

git restore --staged --worktree app.js
# forma corta
git restore -SW app.js

Cómo recuperar un archivo de otro commit o rama

git restore --source=HEAD~2 app.js          # versión de hace dos commits
git restore --source=main config.yml        # versión de la rama main
git restore --source=3f2a1c9 -- docs/       # una carpeta entera de un commit

Por defecto, con --source solo cambia la carpeta de trabajo. Añade --staged si quieres dejar el cambio preparado para el commit. La variante antigua git checkout main -- app.js cambia siempre tanto el índice como la carpeta de trabajo.

Cómo recuperar un archivo borrado

git restore deleted.txt                          # borrado, pero aún sin commit
git restore --source=HEAD~1 deleted.txt          # el borrado ya está en un commit

Si no sabes en qué commit se borró el archivo, búscalo con git log --oneline -- deleted.txt. El último commit de la lista es el que lo borró, y hay que restaurarlo desde su padre: git restore --source=<hash>~1 deleted.txt.

restore, reset y revert: no confundirlos

Los tres comandos «deshacen», pero a distinta profundidad:

  • restore trabaja con los archivos de la carpeta de trabajo y del índice y no modifica el historial. Es seguro para el equipo.
  • reset mueve hacia atrás el puntero de la rama y reescribe el historial. --soft deja los cambios en el índice, --mixed (por defecto) en la carpeta de trabajo y --hard los elimina. Es peligroso con commits ya subidos a ramas compartidas.
  • revert crea un commit nuevo que invierte el indicado. No reescribe el historial, por eso es la forma correcta de deshacer un commit que ya está en el servidor.

Regla sencilla: los cambios aún no tienen commit, restore; el commit solo es local, reset; el commit ya lo tienen tus compañeros, revert.

Detached HEAD después de checkout

Al ejecutar git checkout 3f2a1c9 o git checkout v1.0 verás una larga advertencia «You are in 'detached HEAD' state». Ahora HEAD apunta a un commit y no a una rama. Es útil para ver una versión antigua o lanzar los tests sobre ella.

En este estado se pueden hacer commits, pero los nuevos commits no pertenecerán a ninguna rama. Si has cambiado algo y quieres conservarlo:

git switch -c fix-for-v1

Si solo estabas mirando, vuelve con git switch - o git switch main. Si te has ido sin crear la rama, los commits siguen accesibles mediante git reflog: busca el hash y ejecuta git branch rescue <hash>.

Errores frecuentes

error: pathspec 'feature' did not match any file(s) known to git

Git no ha encontrado ninguna rama ni archivo con ese nombre. Normalmente la rama solo existe en el servidor y no se ha hecho fetch. Ejecuta git fetch y repite. Revisa también cómo está escrito: los nombres de rama distinguen mayúsculas y minúsculas.

He descartado cambios por accidente con checkout -- o restore

Git no guarda las modificaciones sin commit que no estaban en el índice, y no se pueden recuperar con herramientas de Git. Queda el historial local del editor o del IDE. En cambio, si el archivo se había añadido con git add, su contenido está en la base de datos como objeto «colgante» (dangling) y se encuentra con git fsck --lost-found.

Un archivo y una rama con el mismo nombre

git checkout test, si existen la rama test y la carpeta test, mostrará una advertencia de ambigüedad. Usa git switch test para la rama y git restore test (o git checkout -- test) para los archivos.

Situaciones del día a día

Algunos casos que aparecen constantemente y el comando adecuado para cada uno:

  • Empezaste a editar un archivo y te diste cuenta de que ibas por mal camino: git restore archivo.
  • Añadiste al índice un archivo de más antes del commit: git restore --staged archivo.
  • Tienes que pasar de golpe a otra tarea a mitad de trabajo: git stash y después git switch rama; al volver, git switch - y git stash pop.
  • Quieres traer un solo archivo de otra rama sin fusionarla entera: git restore --source=feature/x --staged --worktree ruta.
  • Necesitas comprobar si el bug ya existía en una versión anterior: git switch --detach v1.0, la comprobación y luego git switch -.
  • Quieres deshacer solo una parte de los cambios de un archivo: git restore -p archivo. Git te mostrará cada fragmento y te preguntará si lo descarta.

El modo interactivo -p (--patch) es especialmente útil: existe tanto en checkout como en restore y permite eliminar la salida de depuración conservando los cambios útiles del mismo archivo.

Cómo revisar el resultado antes de deshacer

Restore y checkout con rutas descartan cambios sin pedir confirmación, así que conviene ver primero qué se va a perder. git diff muestra los cambios de la carpeta de trabajo respecto al índice, git diff --staged lo preparado para el commit y git diff main -- app.js en qué se diferencia el archivo de la versión de otra rama. Si tienes dudas, guarda el estado actual con git stash: desde ahí siempre puedes recuperar los cambios, a diferencia de restore.

Resumen

git checkout combina cambiar de rama y restaurar archivos, y precisamente eso lo hace peligroso. Para ramas usa git switch y para archivos git restore: uno solo cambia la posición de HEAD y el otro solo el contenido de los archivos. Las ramas, restore, reset y revert, con escenarios buenos y malos, se practican en el curso de Git.

Preguntas frecuentes

¿Está obsoleto git checkout?

No, no se ha declarado obsoleto y seguirá funcionando. Simplemente, para el trabajo diario se recomiendan git switch y git restore, más específicos y seguros.

¿Desde qué versión de Git existen switch y restore?

Ambos comandos aparecieron en Git 2.23 (año 2019). Puedes comprobar tu versión con git --version.

¿Se puede deshacer un git restore?

Si se restauró la carpeta de trabajo, Git no guardó los cambios descartados y no se puede deshacer. git restore --staged es seguro: los cambios siguen en el archivo y basta con volver a añadirlos con git add.

¿Cómo cambio a la rama de un compañero?

Ejecuta git fetch y después git switch nombre-rama: Git creará una rama local vinculada a origin/nombre-rama.

¿En qué se diferencia git checkout . de git reset --hard?

git checkout . (o git restore .) devuelve los archivos modificados a la versión del índice sin tocar el índice ni el historial. git reset --hard reinicia el índice y la carpeta de trabajo al commit, y si se le pasa un commit como argumento también mueve la rama.

Aprende este tema en vídeo

Este tema se explica a fondo y con práctica en el curso «Git desde cero hasta desarrollador seguro».

Ir al curso