Git

Git

Tutorial Git: Deshacer cambios

Git revert, reset y restore: Aprende a deshacer cambios sin alterar el historial del repositorio, ideal para colaborar en equipo manteniendo la integridad.

Aprende Git y certifícate

git revert: Revertir commits sin reescribir historial

El comando git revert sirve para deshacer cambios introducidos sin alterar el historial existente. A diferencia de git reset, que reescribe el historial, git revert crea un nuevo commit que aplica los cambios inversos al commit especificado.

Para revertir un commit específico, se ejecuta:

git revert <commit>

Donde <commit> es el identificador SHA del commit que se quiera revertir. Por ejemplo, para revertir el último commit realizado:

git revert HEAD

Si se necesita revertir varios commits, se puede hacer individualmente para cada uno o utilizar secuencias de comandos, pero con cuidado para evitar conflictos.

Durante el proceso, Git abre el editor de texto para poder modificar el mensaje del nuevo commit de reversión. Si no se quiere editar el mensaje, se puede utilizar la opción -m para poner un mensaje predeterminado:

git revert -m 1 <merge-commit>

Esta opción se usa mucho al revertir un commit de merge. Para revertir un merge commit hay que especificar el parent al que se quiera volver.

En caso de que haya conflictos al revertir, Git muestra los archivos afectados y es necesario resolverlos. Una vez resueltos, hay que completar el proceso de revert:

git add <archivos_resueltos>
git revert --continue

Si se prefiere aplicar los cambios inversos sin crear un nuevo commit inmediatamente, se puede utilizar la opción --no-commit o -n:

git revert --no-commit <commit>

Esto aplica los cambios al área de staging, pudiendo agrupar varias reversiones en un solo commit posterior.

git reset: Modos --soft, --mixed, --hard y su impacto en el repositorio

El comando git reset sirve para modificar el estado actual del repositorio, moviendo el puntero de la rama actual a un commit específico. Dependiendo del modo utilizado (--soft, --mixed, --hard), se afecta de diferentes maneras el área de staging (índice) y el directorio de trabajo.

  • Modo --soft

Cuando se utiliza git reset --soft <commit>, se mueve el puntero HEAD y el puntero de la rama actual al commit especificado, pero se conservan los cambios en el área de staging. Los archivos modificados permanecen indexados, para que se confirmen de nuevo.

Por ejemplo:

git reset --soft HEAD~1

Este comando retrocede un commit manteniendo los cambios en staging. Es útil si se quieren combinar varios commits en uno solo o modificar el último commit.

  • Modo --mixed (por defecto)

El modo por defecto de git reset es --mixed. Al ejecutar git reset --mixed <commit>, se mueve el puntero HEAD y el de la rama actual al commit especificado, y se actualiza el área de staging para que coincida con ese commit. Sin embargo, los cambios permanecen en el directorio de trabajo, es decir, los archivos modificados no están indexados pero sí presentes en el sistema de archivos.

Ejemplo de uso:

git reset --mixed HEAD~1

Este comando deshace el último commit y los cambios quedan disponibles en el directorio de trabajo para ser revisados o eliminados. Es útil cuando se quieren modificar los cambios antes de confirmarlos de nuevo.

  • Modo --hard

El modo --hard es el más drástico. Al ejecutar git reset --hard <commit>, se mueve el puntero HEAD y el de la rama actual al commit indicado, y además se actualizan el área de staging y el directorio de trabajo para que coincidan exactamente con ese commit. Esto significa que se descartan todos los cambios en el área de staging y en el directorio de trabajo que difieran del commit objetivo.

Ejemplo:

git reset --hard HEAD~1

Este comando elimina el último commit y cualquier cambio pendiente en el área de staging o en el directorio de trabajo. Hay que tener cuidado porque los cambios descartados con --hard no se pueden recuperar fácilmente.

Impacto en el repositorio

El uso de git reset afecta al historial local del repositorio. Al mover el puntero de la rama actual, se reescribe el historial, lo que puede causar problemas al colaborar con otros desarrolladores si los cambios ya han sido compartidos en un repositorio remoto.

  • --soft: Reescribe el historial pero mantiene los cambios en staging. Es seguro usarlo cuando se quiere combinar commits antes de hacer push.
  • --mixed: Reescribe el historial y los cambios se mantienen en el directorio de trabajo. Es útil para ajustar cambios pero no debe usarse si los commits ya fueron publicados.
  • --hard: Reescribe el historial y descarta permanentemente los cambios en staging y en el directorio de trabajo. Debe usarse con cautela y nunca en commits compartidos.

Descartar cambios locales: git restore

Al trabajar en un proyecto, es normal hacer cambios en archivos que luego se quieran descartar sin comprometer el historial del repositorio. Para restaurar un archivo al estado del último commit, se utiliza el comando git restore.

La sintaxis básica es:

git restore <archivo>

Este comando elimina las modificaciones locales no guardadas en los commits, devolviendo el archivo a su versión confirmada más reciente. Por ejemplo, para descartar los cambios en main.c:

git restore main.c

Los cambios descartados de esta manera se pierden definitivamente. Así que se recomienda verificar los cambios con git status antes de proceder.

Descartar cambios en todos los archivos

Si se necesita descartar cambios en todos los archivos modificados, se ejecuta:

git restore .

El punto (.) indica al comando que se aplique a todo el directorio de trabajo.

Descartar archivos del área de staging

Cuando un archivo ha sido agregado al área de staging con git add, pero se decide no incluirlo en el próximo commit, se puede quitar del staging sin perder los cambios locales:

git restore --staged <archivo>

Este comando saca el archivo del área de staging, manteniendo las modificaciones en el directorio de trabajo.

Descartar cambios en staging y directorio de trabajo

Para descartar completamente los cambios de un archivo tanto del área de staging como del directorio de trabajo, se combinan las opciones:

git restore --staged --worktree <archivo>

O utilizando el alias -s y -W:

git restore -sW <archivo>

Previsualización de cambios a descartar

Es posible revisar interactivamente qué cambios se van a descartar utilizando la opción -p:

git restore -p <archivo>

Este modo presenta cada hunk de cambios y permite decidir si se descarta o se mantiene.

Uso de git checkout -- <archivo>

Antes, el comando git checkout -- <archivo> se utilizaba para descartar cambios locales. Aunque sigue funcionando, ahora se recomienda usar git restore.

Ejemplo con git checkout:

git checkout -- main.c

Este comando cumple la misma función que git restore main.c, pero git restore es más claro al diferenciar acciones sobre archivos y ramas.

Precauciones al descartar cambios locales

  • Verificación previa: Antes de descartar cambios, se aconseja utilizar git diff o git status para revisar las modificaciones.
  • Cambios irrecuperables: Una vez descartados, los cambios no se pueden recuperar fácilmente. Se debe estar seguro de que los cambios no son necesarios.
  • Archivos no rastreados: Para eliminar archivos nuevos que no están en seguimiento, se utiliza:
git clean -f <archivo>

El comando git clean elimina archivos no rastreados, por lo que se debe usar con cuidado.

Mejores prácticas: Cuándo preferir revert sobre reset

Elegir cuándo usar git revert en lugar de git reset depende del contexto y del estado de los commits que se quieran deshacer.

Deshacer cambios en commits compartidos

Si los commits que se quieren revertir ya han sido compartidos con otros colaboradores o enviados a un repositorio remoto, hay que utilizar git revert. Este comando crea un nuevo commit que invierte los cambios introducidos por los commits específicos, manteniendo intacto el historial y evitando conflictos.

Por ejemplo:

git revert <commit>

De este modo se mantiene un historial intacto.

Reescritura del historial en commits locales

git reset se usa cuando se necesita modificar el historial local de commits que aún no han sido compartidos. Permite mover el puntero de la rama a un commit anterior y ajustar el área de staging y el directorio de trabajo según se necesite.

Por ejemplo, para deshacer los últimos tres commits sin afectar los archivos del directorio de trabajo:

git reset --soft HEAD~3

Es importante evitar usar git reset en commits que ya han sido publicados, ya que reescribir el historial puede causar problemas de sincronización.

Colaboración y prevención de conflictos

En proyectos donde varias personas trabajan sobre la misma rama, utilizar git revert ayuda a preservar un historial lineal. Los revertidos quedan registrados, y así se puede seguir qué cambios se han deshecho y por qué.

Usar git reset en estos casos puede provocar conflictos, porque otros desarrolladores pueden haber basado su trabajo en los commits que se están eliminando del historial.

Uso seguro de git reset

git reset es útil en situaciones como:

  • Corrección de errores en commits recientes antes de compartirlos.
  • Limpieza del historial local durante el desarrollo personal.

Siempre se debe confirmar que los commits afectados no han sido enviados al repositorio remoto. De lo contrario, es preferible utilizar git revert para mantener la coherencia.

Procedimientos recomendados

Para garantizar un buen flujo de trabajo:

  • Utilizar git revert cuando se trabaja en ramas compartidas o al deshacer cambios ya publicados.
  • Emplear git reset solo en ramas locales y con commits no compartidos.
  • Comunicar al equipo cualquier operación que pueda afectar al historial compartido.
  • Evitar reescribir el historial en ramas públicas para prevenir problemas de integración.

Integridad del proyecto y herramientas de integración continua

En entornos con integración continua y despliegue automatizado, se necesita mantener un historial consistente. git revert es la opción más segura, ya que las herramientas de automatización dependen de un historial sin alteraciones para funcionar correctamente.

Reescribir el historial con git reset puede interrumpir estos procesos y desencadenar fallos en las compilaciones o despliegues.

CONSTRUYE TU CARRERA EN IA Y PROGRAMACIÓN SOFTWARE

Accede a +1000 lecciones y cursos con certificado. Mejora tu portfolio con certificados de superación para tu CV.

30 % DE DESCUENTO

Plan mensual

19.00 /mes

13.30 € /mes

Precio normal mensual: 19 €
63 % DE DESCUENTO

Plan anual

10.00 /mes

7.00 € /mes

Ahorras 144 € al año
Precio normal anual: 120 €
Aprende Git online

Ejercicios de esta lección Deshacer cambios

Evalúa tus conocimientos de esta lección Deshacer cambios con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de Git

Accede a todas las lecciones de Git y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a Git y certifícate

Certificados de superación de Git

Supera todos los ejercicios de programación del curso de Git y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender el comando git revert y su funcionamiento.
  • Diferenciar entre git revert y git reset.
  • Aplicar git revert para deshacer cambios en commits compartidos.
  • Manejar conflictos al revertir commits.
  • Utilizar opciones para modificar el mensaje del commit de reversión.