HDP115

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.

CE

Cristian Escalante

Última actualización: 30 de abril de 2025

git
control de versiones
desarrollo
recuperación

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:

  1. Cambios no preparados: Modificaciones en tu directorio de trabajo que aún no han sido añadidas al área de preparación (staging)
  2. Cambios preparados: Cambios que están en el área de preparación pero aún no se han confirmado
  3. Commits locales: Cambios confirmados que aún no se han enviado al repositorio remoto
  4. 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 commit
  • reword: cambiar el mensaje
  • edit: pausar para modificar
  • squash: combinar con el commit anterior
  • fixup: como squash, pero descartar el mensaje
  • drop: 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

EscenarioComando moderno (Git 2.23+)Comando tradicional
Descartar cambios no preparadosgit restore <archivo>git checkout -- <archivo>
Quitar del staginggit restore --staged <archivo>git reset HEAD <archivo>
Modificar último commitgit commit --amendgit commit --amend
Deshacer commit localgit reset [--soft/--mixed/--hard] HEAD~1git reset [--soft/--mixed/--hard] HEAD~1
Deshacer commit publicadogit 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.

Uso de git stash para guardar trabajo temporal
Aprende a utilizar el comando git stash para guardar tempora...
Búsqueda en el historial
Aprende técnicas avanzadas para buscar y filtrar información...
Referencias
Git. Git - git-restore Documentation. https://git-scm.com/docs/git-restore
Scott Chacon and Ben Straub. Pro Git Book - Undoing Things. https://git-scm.com/book/en/v2/Git-Basics-Undoing-Things
Scott Chacon. Git - Reset Demystified. https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified
Atlassian. Atlassian Git Tutorial - Undoing Changes. https://www.atlassian.com/git/tutorials/undoing-changes

Conceptos Básicos de HTML

Aprende los conceptos básicos de HTML

Conceptos Básicos de CSS

Aprende los conceptos básicos de CSS

Conceptos Básicos de JavaScript

Aprende los conceptos básicos de JavaScript

Conceptos Básicos SQL

Aprende los conceptos básicos de SQL

Conceptos Básicos de Python

Aprende los conceptos básicos de Python

Conceptos Básicos de UML

Aprende los conceptos básicos de UML

Refuerzo Academico de Herramientas de Productividad 2025