Cómo deshacer cambios en Git
Aprende las diferentes formas de deshacer cambios en Git, desde modificaciones locales hasta commits publicados, y domina las técnicas para mantener un historial limpio y recuperarte de errores.
Cristian Escalante
Última actualización: 30 de abril de 2025
Cómo deshacer cambios en Git
Cometer errores es parte natural del desarrollo de software. Afortunadamente, Git ofrece varias formas de "deshacer" cambios, desde simples modificaciones en tu directorio de trabajo hasta commits que ya han sido publicados en un repositorio remoto. Dominar estas técnicas te permitirá trabajar con confianza, sabiendo que siempre puedes recuperarte de casi cualquier situación.
Niveles de deshacer cambios
En Git, puedes deshacer cambios en diferentes niveles:
- Cambios no preparados: Modificaciones en tu directorio de trabajo que aún no han sido añadidas al área de preparación (staging)
- Cambios preparados: Cambios que están en el área de preparación pero aún no se han confirmado
- Commits locales: Cambios confirmados que aún no se han enviado al repositorio remoto
- Commits publicados: Cambios que ya han sido compartidos con otros
Cada nivel requiere diferentes comandos y técnicas, que veremos a continuación.
Deshacer cambios no preparados
Usando git restore (Git 2.23+)
Para descartar cambios en archivos modificados que aún no han sido añadidos al área de preparación:
# Descartar cambios en un archivo específico
git restore <archivo>
# Descartar cambios en todos los archivos modificados
git restore .
Usando git checkout (método tradicional)
# Descartar cambios en un archivo específico
git checkout -- <archivo>
# Descartar cambios en todos los archivos modificados
git checkout -- .
Recuperar archivos eliminados
Si eliminaste un archivo pero aún no has hecho commit:
git restore <archivo-eliminado>
# o
git checkout -- <archivo-eliminado>
Deshacer cambios preparados (staged)
Quitar del área de preparación
Para quitar cambios del área de preparación sin perderlos (siguen en tu directorio de trabajo):
# Usando git restore (Git 2.23+)
git restore --staged <archivo>
# Usando git reset
git reset HEAD <archivo>
Descartar cambios preparados completamente
Para quitar cambios del área de preparación y descartarlos completamente:
git restore --staged <archivo> # Primero quitar del staging
git restore <archivo> # Luego descartar los cambios
Modificar el último commit
Cambiar el mensaje del último commit
git commit --amend -m "Nuevo mensaje de commit"
Añadir cambios al último commit
# Añadir más cambios al staging
git add archivo-olvidado.txt
# Incluirlos en el último commit
git commit --amend --no-edit # Mantiene el mismo mensaje
Importante: No uses
--amend
en commits que ya hayas compartido (pushed), ya que reescribe la historia.
Deshacer commits locales
Usando git reset
git reset
mueve la rama actual a un commit específico, permitiéndote "deshacer" commits.
Soft reset
Mueve la rama pero mantiene los cambios en el área de preparación:
# Deshacer el último commit manteniendo los cambios preparados
git reset --soft HEAD~1
Útil cuando quieres reorganizar o combinar commits.
Mixed reset (predeterminado)
Mueve la rama y quita los cambios del área de preparación, pero los mantiene en tu directorio de trabajo:
# Deshacer el último commit y quitar los cambios del staging
git reset HEAD~1
# o
git reset --mixed HEAD~1
Útil cuando quieres rehacer un commit desde cero.
Hard reset
Mueve la rama y descarta todos los cambios, volviendo tu directorio de trabajo al estado del commit especificado:
# Deshacer el último commit y descartar todos los cambios
git reset --hard HEAD~1
¡Precaución!
git reset --hard
descarta permanentemente los cambios. Úsalo con cuidado.
Deshacer múltiples commits
Puedes especificar cuántos commits quieres deshacer:
# Deshacer los últimos 3 commits
git reset --soft HEAD~3
O especificar un commit específico al que volver:
# Volver a un commit específico
git reset --mixed 7f6d03
Deshacer commits publicados
Para cambios que ya han sido compartidos con otros, no debes usar reset
ya que reescribe la historia. En su lugar, usa revert
.
Usando git revert
git revert
crea un nuevo commit que deshace los cambios de un commit anterior:
# Revertir el último commit
git revert HEAD
# Revertir un commit específico
git revert abc123
Revertir múltiples commits
# Revertir un rango de commits (no incluye a 'desde')
git revert desde..hasta
# Ejemplo: revertir los últimos 3 commits
git revert HEAD~2..HEAD
Revert sin commit automático
Si quieres revertir cambios pero no crear un commit automáticamente:
git revert --no-commit HEAD~3..HEAD
# Ahora puedes hacer ajustes si es necesario
git commit -m "Revierte los últimos 3 commits"
Recuperar después de un reset --hard
Si usaste git reset --hard
y perdiste cambios importantes, aún hay esperanza:
Usando git reflog
git reflog
muestra un registro de dónde ha estado HEAD, permitiéndote recuperar commits "perdidos":
# Ver el registro de referencias
git reflog
# Ejemplo de salida:
# 7f6d03 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~3
# abc123 HEAD@{1}: commit: Añade funcionalidad X
# def456 HEAD@{2}: commit: Implementa Y
# ...
# Recuperar al estado anterior al reset
git reset --hard abc123
Límites de recuperación
La recuperación con reflog
tiene límites:
- Solo funciona con commits que han sido guardados en tu repositorio local
- Git limpia el reflog periódicamente (por defecto, entradas más antiguas de 90 días)
- No funciona si nunca hiciste commit de los cambios
Técnicas avanzadas
Rebase interactivo
Para reorganizar, editar, combinar o eliminar commits:
# Modificar los últimos 3 commits
git rebase -i HEAD~3
Esto abrirá un editor donde puedes:
pick
: mantener el commitreword
: cambiar el mensajeedit
: pausar para modificarsquash
: combinar con el commit anteriorfixup
: como squash, pero descartar el mensajedrop
: eliminar el commit
Cherry-pick
Para aplicar cambios específicos de un commit a tu rama actual:
git cherry-pick abc123
Recuperar archivos específicos de commits antiguos
# Recuperar una versión anterior de un archivo sin cambiar HEAD
git checkout abc123 -- ruta/al/archivo
Casos de uso comunes
Deshacer un merge reciente
# Si el merge se acaba de hacer y no se ha publicado
git reset --hard ORIG_HEAD
# Si el merge ya se ha publicado
git revert -m 1 <commit-de-merge>
Limpiar archivos no rastreados
# Ver qué archivos se eliminarían
git clean -n
# Eliminar archivos no rastreados
git clean -f
# Eliminar archivos no rastreados e ignorados
git clean -fdx
Deshacer todos los cambios locales
# Restablecer el directorio de trabajo al último commit
git reset --hard HEAD
Deshacer un rebase publicado
Si hiciste un rebase y luego un push forzado, la mejor solución es comunicarte con tu equipo, ya que esto puede causar problemas a otros desarrolladores.
Buenas prácticas
1. Haz commits frecuentes
Los commits pequeños y frecuentes facilitan deshacer cambios específicos sin afectar demasiado trabajo.
2. Crea ramas para experimentos
Usa ramas para experimentos arriesgados, así puedes simplemente eliminar la rama si las cosas salen mal.
3. Verifica antes de ejecutar comandos destructivos
Usa comandos como git status
, git diff
y git log
para verificar el estado antes de ejecutar comandos que pueden descartar cambios.
4. Usa --dry-run cuando esté disponible
Algunos comandos tienen opciones como --dry-run
que muestran qué pasaría sin realizar cambios reales.
5. No reescribas la historia pública
Evita usar reset
, amend
o rebase
en commits que ya han sido compartidos con otros.
6. Crea copias de seguridad para operaciones arriesgadas
Antes de operaciones complejas o arriesgadas, considera:
# Crear una rama de respaldo
git branch backup-branch
# O hacer un clon del repositorio
cp -r mi-repo mi-repo-backup
Comparación de comandos para deshacer
Escenario | Comando moderno (Git 2.23+) | Comando tradicional |
---|---|---|
Descartar cambios no preparados | git restore <archivo> | git checkout -- <archivo> |
Quitar del staging | git restore --staged <archivo> | git reset HEAD <archivo> |
Modificar último commit | git commit --amend | git commit --amend |
Deshacer commit local | git reset [--soft/--mixed/--hard] HEAD~1 | git reset [--soft/--mixed/--hard] HEAD~1 |
Deshacer commit publicado | git revert <commit> | git revert <commit> |
Conclusión
Git proporciona herramientas poderosas para deshacer cambios en todos los niveles del flujo de trabajo. La clave está en entender en qué estado se encuentran tus cambios y elegir el comando adecuado para la situación.
Recuerda que mientras algunos comandos como restore
y revert
son seguros porque no reescriben la historia, otros como reset --hard
y commit --amend
pueden causar pérdida de datos o problemas de colaboración si se usan incorrectamente.
Con práctica, aprenderás a elegir la herramienta correcta para cada situación, lo que te dará confianza para experimentar sabiendo que siempre puedes volver a un estado conocido si algo sale mal.