Git: Switch, Restore, Reset y Revert

Git: switch, restore, reset y revert

Guía práctica y técnica para cambiar de ramas, recuperar archivos, deshacer commits y reparar errores sin destruir el historial.

Git permite realizar prácticamente cualquier operación sobre el historial de un proyecto, pero precisamente por eso algunos comandos pueden resultar peligrosos si no se entiende exactamente qué referencia, archivo o estado están modificando.

Cuatro comandos permiten separar claramente diferentes tipos de operaciones que durante años estuvieron concentradas principalmente en git checkout:

  • git switch → trabajar con ramas y HEAD.
  • git restore → trabajar con archivos, staging y working tree.
  • git reset → mover referencias y, según el modo utilizado, modificar el staging y el working tree.
  • git revert → crear nuevos commits que deshacen cambios anteriores.
Idea fundamental: antes de ejecutar un comando potencialmente destructivo en Git, determina qué quieres modificar: la rama, el staging area, el working tree o el historial compartido.

Guía rápida: ¿qué comando necesitas ahora?

¿Quieres cambiar de rama?
→ git switch

¿Quieres crear una rama?
→ git switch -c nombre-rama

¿Quieres descartar cambios locales de un archivo?
→ git restore archivo

¿Quieres quitar un archivo del staging sin perder sus cambios?
→ git restore --staged archivo

¿Quieres recuperar un archivo de otro commit?
→ git restore --source COMMIT -- archivo

¿Quieres eliminar commits locales antes de hacer push?
→ git reset

¿Quieres deshacer un commit que ya está publicado?
→ git revert

¿Has hecho un reset y necesitas recuperar el estado anterior?
→ git reflog

¿Por qué necesitas dominar estos comandos?

Los problemas reales con Git rara vez aparecen cuando todo funciona correctamente. Aparecen cuando necesitas recuperar algo, deshacer un cambio o reparar una situación que ya ha llegado al repositorio remoto.

Situación 1: “Hice commit de un archivo con credenciales por accidente”.

Aquí no basta necesariamente con borrar el archivo del proyecto. Si las credenciales quedaron registradas en el historial, siguen formando parte del repositorio y deben considerarse comprometidas.

Situación 2: “Necesito comprobar cómo estaba el código antes del último cambio”.

En este caso probablemente no quieres modificar el historial. Solo necesitas inspeccionar una versión anterior o recuperar determinados archivos.

Situación 3: “Desplegué un bug a producción y necesito revertirlo YA”.

Si el commit ya está publicado y otros desarrolladores trabajan sobre él, normalmente la solución adecuada es git revert, no reescribir la historia con git reset.

Situación 4: “He hecho varios commits locales y quiero volver atrás antes de hacer push”.

Aquí git reset puede ser exactamente la herramienta adecuada, especialmente si esos commits todavía no han sido compartidos.

Antes de tocar nada: entiende los estados de Git

Para entender switch, restore, reset y revert es necesario distinguir las diferentes partes del estado de un repositorio.

Zona Qué contiene Ejemplo
HEAD Referencia al commit actualmente comprobado. Cuando estás sobre una rama, normalmente HEAD apunta a esa rama. HEAD -> main
Staging Area / Index Estado de los archivos que se utilizará para construir el próximo commit. git add archivo.js
Working Tree Los archivos que tienes físicamente en tu directorio de trabajo. Archivos modificados localmente

Una forma sencilla de visualizar la relación:

          HEAD
           │
           ▼
        COMMIT
           │
           ▼
     STAGING AREA
           │
           ▼
      WORKING TREE

Muchos errores con Git ocurren porque se utiliza un comando pensando que afecta a una zona cuando en realidad afecta a otra.

Git Switch: cambiar y crear ramas

git switch está diseñado específicamente para trabajar con ramas y HEAD.

¿Cuándo utilizarlo?

  • Para cambiar a una rama existente.
  • Para crear una rama nueva.
  • Para crear una rama a partir de otra referencia.
  • Para volver rápidamente a la rama anterior.
  • Para inspeccionar un commit mediante detached HEAD.

Cambiar a una rama existente

git switch develop
Cambia la rama actual a develop.

La operación equivalente con checkout sería:

git checkout develop

git switch deja más clara la intención: quiero cambiar de rama.

Crear una rama y cambiar a ella

git switch -c nueva-feature
Crea nueva-feature desde la posición actual y cambia a ella.

Equivalente:

git checkout -b nueva-feature

Crear una rama desde una referencia concreta

git switch -c hotfix v1.4.2
Crea hotfix partiendo del tag v1.4.2.

Esto resulta especialmente útil cuando necesitas preparar una corrección partiendo exactamente de una versión publicada.

Volver a la rama anterior

git switch -
Vuelve a la rama en la que estabas anteriormente.
git switch main
# trabajo...

git switch develop
# trabajo...

git switch -
# vuelve a main

Detached HEAD

git switch --detach abc123
Coloca HEAD directamente sobre el commit abc123.

Esto resulta útil para inspeccionar, ejecutar o probar una versión concreta sin mover ninguna rama.

git switch --detach abc123

git status

# HEAD detached at abc123
⚠️ Importante: detached HEAD no significa que hayas roto Git. Simplemente significa que HEAD apunta directamente a un commit en lugar de apuntar a una rama.

Si durante ese estado realizas commits y quieres conservarlos de forma permanente mediante una rama:

git switch -c investigacion-bug

Git Restore: recuperar y descartar archivos

git restore está diseñado principalmente para trabajar con el contenido de los archivos, tanto en el working tree como en el staging area.

Es especialmente útil cuando necesitas recuperar archivos o eliminar modificaciones locales.

Descartar cambios locales de un archivo

git restore archivo.js
Restaura el archivo utilizando el contenido del índice y descarta las modificaciones no staged del working tree.
⚠️ Atención: los cambios descartados de esta forma pueden ser difíciles o imposibles de recuperar. Comprueba primero git diff.

Comprobar antes de restaurar

git status
git diff
git restore archivo.js

Este pequeño hábito puede evitar muchos accidentes.

Descartar cambios de todos los archivos

git restore .
Descarta las modificaciones no staged de los archivos afectados bajo la ruta actual.

No debería ejecutarse a ciegas en un proyecto con trabajo local importante.

📌 Nota: git restore solo afecta a archivos trackeados. Los archivos nuevos no añadidos (untracked) no se tocan. Si además quieres eliminar archivos sin seguimiento (generados por builds, logs, etc.), usa git clean -fd con extrema precaución.

Quitar un archivo del staging

git restore --staged archivo.js
Retira el archivo del staging, pero mantiene sus modificaciones en el working tree.
git add archivo.js

git restore --staged archivo.js

El archivo deja de estar preparado para el commit, pero no se pierden sus cambios.

Recuperar un archivo desde un commit anterior

git restore --source abc123 -- archivo.js
Recupera la versión de archivo.js existente en abc123 y la coloca en el working tree.

Este comando resulta especialmente útil cuando quieres rescatar un archivo concreto sin retroceder toda la rama.

Importante: git restore --source no coloca HEAD en detached HEAD. El comando modifica el contenido del archivo en tu working tree; la rama actual continúa siendo la misma.

Git Reset: mover una rama hacia atrás

git reset es conceptualmente diferente de git restore.

Mientras restore está orientado principalmente al contenido de archivos, reset puede mover la referencia de la rama y modificar el estado del staging y del working tree dependiendo de la opción utilizada.

Por eso debe utilizarse con más precaución.

Los tres modos principales

1. --soft

git reset --soft HEAD~1
Mueve la referencia de la rama un commit hacia atrás y mantiene los cambios preparados en staging.
git commit -m "Commit incorrecto"

git reset --soft HEAD~1

# Los cambios siguen staged

git commit -m "Commit corregido"

💡 Caso de uso avanzado: fusionar varios commits locales (squash)
git reset --soft HEAD~3
Deshace los últimos 3 commits pero deja todos los cambios en el staging, permitiendo crear un único commit limpio.
# Tienes 3 commits feos y quieres fusionarlos en 1 antes de hacer push
git reset --soft HEAD~3
git commit -m "Feature completa y limpia"

2. --mixed

git reset HEAD~1
Mueve la referencia de la rama y actualiza el staging, pero conserva los cambios en el working tree.

--mixed es el comportamiento predeterminado de git reset.

3. --hard

git reset --hard HEAD~3
Mueve la rama y hace que el índice y el working tree coincidan con el commit de destino, descartando cambios que no estén en ese commit.
☢️ ADVERTENCIA: git reset --hard puede eliminar cambios locales no guardados. Además, si mueve una rama que ya ha sido compartida, puede provocar divergencias y requerir una reescritura del historial remoto.

¿Cuándo tiene sentido utilizar reset --hard?

Principalmente cuando estás trabajando en una rama local y tienes claro que quieres abandonar el estado actual.

git status

git log --oneline -5

git reset --hard HEAD~2

Antes de ejecutar el comando, asegúrate de que realmente quieres eliminar el estado actual.

Git Reflog: la red de seguridad

Uno de los mecanismos más importantes para recuperar estados aparentemente perdidos es:

git reflog

El reflog registra movimientos recientes de referencias locales, incluidos cambios producidos por operaciones como reset.

git reflog

abc1234 HEAD@{0}: reset: moving to HEAD~2
def5678 HEAD@{1}: commit: Añadir nueva API
987abcd HEAD@{2}: commit: Corregir autenticación

Si descubres que el reset fue un error, puedes localizar el estado anterior y recuperar la referencia:

git reset --hard def5678

📋 Cómo leer y elegir una entrada del reflog:
git reflog -10
Muestra las últimas 10 operaciones. Cada línea tiene un hash y un marcador tipo HEAD@{n}. Elige el estado al que quieras volver y ejecuta git reset --hard HEAD@{n}.
# Ejemplo real
git reflog
# a1b2c3d HEAD@{5}: commit: Mensaje importante
# e4f5g6h HEAD@{6}: commit: Otro cambio

# Vuelves al estado de HEAD@{5}
git reset --hard a1b2c3d
⚠️ Importante: reflog no es un historial remoto ni una garantía de recuperación permanente. Las entradas del reflog pueden caducar y los objetos inaccesibles pueden terminar siendo eliminados mediante los procesos de mantenimiento de Git.

Git Revert: deshacer sin reescribir el historial

git revert utiliza una estrategia completamente diferente.

En lugar de mover la rama hacia atrás, crea un nuevo commit que invierte los cambios introducidos por otro commit.

A --- B --- C
              ↑
             HEAD

Si ejecutamos:

git revert C

Git crea otro commit:

A --- B --- C --- C'
                  ↑
                 HEAD

C' contiene los cambios necesarios para deshacer el efecto de C.

Ventaja clave: el historial original continúa existiendo y la operación puede compartirse mediante push sin reescribir la historia de los demás desarrolladores.

Revertir el último commit

git revert HEAD
Crea un nuevo commit que invierte el último commit.

Revertir un commit concreto

git revert abc123
Crea un commit que deshace los cambios introducidos por abc123.

Revertir sin abrir el editor del mensaje

git revert --no-edit abc123
Utiliza el mensaje generado automáticamente.

Revertir un rango de commits

git revert abc123..xyz789
Solicita revertir los commits alcanzables desde xyz789 pero no desde abc123.
⚠️ Atención con los rangos: la sintaxis A..B significa normalmente “alcanzables desde B pero no desde A”. Antes de revertir muchos commits conviene inspeccionar exactamente qué commits entran en el rango.
git log --oneline abc123..xyz789

Revert y conflictos

Un revert no siempre puede aplicarse automáticamente.

Si los cambios posteriores modificaron las mismas líneas que el commit que quieres revertir, Git puede producir un conflicto.

git revert abc123

# Si aparecen conflictos:

git status

# Resolver manualmente los archivos

git add archivo-resuelto.js

git revert --continue

Si decides cancelar la operación:

git revert --abort

Reset vs Revert: la diferencia fundamental

Característica reset revert
Qué hace Mueve una referencia y puede modificar índice y working tree Crea un nuevo commit que invierte cambios anteriores
Reescribe historia Sí, cuando mueve una rama No
Puede modificar el working tree Sí, especialmente con --hard No directamente
Adecuado para commits publicados Generalmente no Sí
Genera un commit nuevo No Sí

Switch vs Restore vs Reset vs Revert

Comando Propósito principal Actúa principalmente sobre Reescribe historial Riesgo
git switch Cambiar o crear ramas HEAD / ramas No Bajo
git restore Restaurar archivos Working tree / staging No Bajo (si especificas archivo) / Medio-alto (si usas .)
git reset Mover referencias HEAD / staging / working tree Sí, cuando mueve una rama Medio-alto
git revert Deshacer commits Historial mediante nuevo commit No Bajo-medio

Flujo de trabajo recomendado

Para cambiar de rama

# Con checkout
git checkout main

# Con switch
git switch main

Para crear una rama

# Con checkout
git checkout -b nueva-rama

# Con switch
git switch -c nueva-rama

Para restaurar un archivo

# Con checkout
git checkout -- archivo.js

# Con restore
git restore archivo.js

Para recuperar un archivo desde un commit

# Con checkout
git checkout abc123 -- archivo.js

# Con restore
git restore --source abc123 -- archivo.js
Nota: git checkout sigue existiendo y continúa siendo válido. git switch y git restore permiten expresar de forma más específica si la intención es trabajar con ramas o con archivos.

Un caso real: metí un archivo sensible en un commit

Supongamos que accidentalmente hiciste:

git add .
git commit -m "Configuración"
git push

y descubriste que habías incluido un archivo como:

.env
config/secrets.json
credentials.json
🚨 Si una contraseña, API key, token o credencial ha sido publicada, considérala comprometida.

Eliminar el archivo en un commit posterior no hace que la credencial deje de existir en el historial anterior.

El procedimiento depende de si el commit se ha publicado y del tipo de secreto. En primer lugar:

git status
git log --oneline --all --decorate -10

📌 Importante: git reset y git revert no eliminan el archivo del historial. La credencial seguirá accesible mediante el hash del commit. Para limpiar el historial de forma efectiva, necesitas herramientas como git filter-repo (recomendada oficialmente) o BFG Repo-Cleaner. Estas reescriben el historial eliminando el archivo sensible de todos los commits.
# Ejemplo con filter-repo (requiere instalación)
git filter-repo --path secrets.json --invert-paths

# O con BFG (alternativa)
bfg --delete-files secrets.json

Si el secreto es real, la prioridad debería ser revocar o rotar la credencial. Después se puede estudiar la limpieza del historial. En un repositorio compartido no conviene improvisar un reset --hard o un force-push sin la coordinación adecuada con el equipo.

Un caso real: necesito recuperar una versión anterior

Primero inspecciona el historial:

git log --oneline --decorate --graph --all

Si solo quieres examinar un commit:

git switch --detach abc123

Si quieres recuperar únicamente un archivo:

git restore --source abc123 -- archivo.js

Si quieres volver permanentemente la rama a un commit anterior y todavía estás trabajando localmente:

git reset --hard abc123

Son tres operaciones completamente diferentes, aunque las tres puedan aparecer en una situación de “quiero volver atrás”.

Un caso real: bug desplegado en producción

Imagina este historial:

A --- B --- C --- D
                  ↑
              commit con bug

Si D ya está en producción y forma parte de una rama compartida, normalmente quieres mantener el historial y crear un commit correctivo:

git revert D

El resultado conceptual:

A --- B --- C --- D --- R
                        ↑
                    deshace D

Después puedes revisar, probar y publicar el nuevo commit:

git status
git push

Esto permite que todos los miembros del equipo vean exactamente qué ocurrió.

Buenas prácticas antes de ejecutar comandos destructivos

Antes de utilizar reset --hard, borrar cambios o manipular ramas, acostúmbrate a ejecutar:

git status
git branch --show-current
git log --oneline --decorate -10
git diff

Y si vas a manipular commits:

git reflog -10

Estas comprobaciones tardan segundos y pueden evitar perder horas de trabajo.

Regla de oro

Si el historial ya está compartido, piensa dos veces antes de reescribirlo.

Si el cambio solo existe localmente, tienes mucha más libertad para utilizar reset.

Si quieres modificar archivos, piensa en restore.

Si quieres cambiar de rama, piensa en switch.

Si quieres deshacer un commit publicado sin reescribir la historia, piensa en revert.

Tabla definitiva: ¿qué comando necesito?

Problema Comando recomendado
Cambiar de rama git switch rama
Crear una rama git switch -c rama
Volver a la rama anterior git switch -
Inspeccionar un commit git switch --detach COMMIT
Descartar cambios locales git restore archivo
Descartar cambios de varios archivos git restore .
Quitar del staging git restore --staged archivo
Recuperar un archivo antiguo git restore --source COMMIT -- archivo
Rehacer el último commit local git reset --soft HEAD~1
Fusionar varios commits locales (squash) git reset --soft HEAD~N
Volver atrás conservando archivos modificados git reset --mixed COMMIT
Eliminar estado local y volver a un commit git reset --hard COMMIT
Recuperar un estado después de un reset git reflog
Deshacer un commit publicado git revert COMMIT

Conclusión

La separación entre git switch y git restore permite distinguir con mayor claridad dos operaciones que históricamente podían realizarse mediante git checkout: trabajar con ramas y trabajar con archivos.

La forma de pensar en estos comandos puede resumirse así:

RAMAS       → git switch
ARCHIVOS    → git restore
REFERENCIAS → git reset
DESHACER    → git revert
RECUPERAR   → git reflog

Una vez entiendes esta separación, Git deja de parecer una colección arbitraria de comandos y empieza a comportarse como lo que realmente es: un sistema de objetos y referencias donde cada operación modifica una parte concreta del estado del repositorio.

¿Te resultó útil esta guía?
Guárdala como referencia antes de ejecutar un comando destructivo. En Git, cinco segundos leyendo git status pueden ahorrarte horas de recuperación.

Visitas: 18

Automation & Data Specialist | Web Development | Data Processing & Integration

Si continuas utilizando este sitio aceptas el uso de cookies. más información

Los ajustes de cookies de esta web están configurados para "permitir cookies" y así ofrecerte la mejor experiencia de navegación posible. Si sigues utilizando esta web sin cambiar tus ajustes de cookies o haces clic en "Aceptar" estarás dando tu consentimiento a esto.

Cerrar