Git básico

Deshacer sin romper nada

Lección 5 de 8 · 15 min

La pregunta correcta antes de deshacer

Casi todo el mundo llega aquí escribiendo en el buscador «cómo deshacer en Git» y copiando el primer comando que aparece. Ese comando suele ser git reset --hard, y es el único de esta lección que borra trabajo sin preguntar.

Antes de deshacer nada hay que responder dos preguntas. Con ellas, el comando correcto sale solo.

1. ¿Ya hiciste commit? Si no, el cambio está suelto y deshacerlo no afecta a nadie.
2. ¿Ya lo compartiste? Si el commit ya está en un servidor o en el equipo de otra persona, deja de ser tuyo: se corrige añadiendo, no borrando.

Los cuatro escenarios

Con esas dos preguntas, todo lo que te va a pasar cabe en cuatro casos. Esta es la tabla que conviene tener a mano las primeras semanas.

Cada situación con su comando

1. Cambié un archivo y no hice commit

Quieres el archivo como estaba en el último commit.

git restore cotizacion.md

Ojo: tus cambios de ese archivo se pierden, porque nunca llegaron a guardarse en ningún sitio. Es el único caso de esta lección donde no hay red.

2. Preparé de más con git add

El archivo no debía entrar en el próximo commit.

git restore --staged notas.txt

Solo lo saca del área de preparación. El contenido no se toca: sigue modificado en tu carpeta.

3. Hice commit y NO lo he compartido

Puedes rehacerlo, porque solo existe en tu equipo.

git reset --soft HEAD~1 deshace el commit y conserva tus cambios preparados, listos para rehacerlo bien.

Si solo era el mensaje: git commit --amend.

4. Hice commit y YA lo compartí

No se borra: se corrige con un commit nuevo que hace lo contrario.

git revert a91c4e2

El historial crece en vez de cambiar, y nadie se queda con una versión distinta de la historia.

Las tres variantes de reset, que es donde se equivoca todo el mundo

git reset mueve la rama hacia atrás. Lo que cambia entre sus tres formas es qué hace con tu trabajo, y esa diferencia es la que separa «deshacer» de «perder».

La misma orden, tres resultados muy distintos
# Deshace el commit. Los cambios quedan PREPARADOS, listos para rehacerlo.
git reset --soft HEAD~1

# Deshace el commit. Los cambios quedan en la carpeta, SIN preparar.
git reset --mixed HEAD~1        # es el modo por defecto

# Deshace el commit y BORRA los cambios. No hay papelera.
git reset --hard HEAD~1

--hard es el único comando de este curso que destruye trabajo. No hay confirmación, no hay papelera y no pregunta dos veces. Es el que más se recomienda en los foros porque «deja todo limpio», y es la razón por la que hay gente que le tiene miedo a Git.

Regla sencilla: si dudas, usa --soft. Deshace exactamente igual y deja tus cambios ahí para que decidas.

Por qué no se reescribe lo que ya se compartió

reset y commit --amend no modifican un commit: crean otro distinto, con otro identificador, y hacen como si el anterior no hubiera existido.

Mientras eso ocurre solo en tu equipo, es inofensivo. Pero si ese commit ya estaba en el servidor, tus compañeros tienen en su historial uno que en el tuyo ya no existe, y a partir de ahí cada persona trabaja sobre una versión distinta de la misma historia. Deshacer eso cuesta mucho más que el error original.

La forma segura: corregir añadiendo
# Que commit quiero anular
git log --oneline

# Crea un commit NUEVO que deshace exactamente aquel
git revert a91c4e2
Resultado
a91c4e2 fix: el domicilio se cobra aparte en la cotizacion

[main 3f8b2d1] Revert "fix: el domicilio se cobra aparte en la cotizacion"
 1 file changed, 2 deletions(-), 1 insertion(+)

Fíjate en que los dos commits siguen ahí: el original y el que lo anula. Cualquiera que mire el historial entiende qué se hizo y qué se echó atrás. Eso es exactamente lo que se quiere en un repositorio compartido.

Caso real: hice commits en main y debían ir en una rama

  1. Comprobar dónde estás y qué hiciste

    git status y git log --oneline -3. Confirma que los últimos commits están en main y cuántos son.

  2. Crear la rama aquí mismo

    git switch -c feature/cotizacion-por-zonas

    La rama nace apuntando a donde estás, así que se lleva tus commits. Ya están a salvo.

  3. Devolver main a su sitio

    git switch main y luego git reset --hard HEAD~2 si eran dos commits.

    Aquí --hard sí es correcto y no pierdes nada: los commits están en la rama que acabas de crear. Es la única situación de este curso donde se usa.

  4. Verificar antes de seguir

    git log --oneline --graph --all. Tienes que ver tus commits colgando de la rama nueva y main en el punto anterior. Si no se ve así, no sigas: mira el paso siguiente.

La red de seguridad que casi nadie conoce

Si ya ejecutaste algo destructivo y crees que perdiste commits, todavía queda una carta. Git anota cada movimiento de tus ramas en un registro aparte, y ahí siguen los commits que ya no aparecen en el historial.

Recuperar un commit que ya no se ve
# Todo lo que hizo tu rama, incluido lo que deshiciste
git reflog

# Volver al estado anterior al desastre
git reset --hard 7d3b8f1
Resultado
3f8b2d1 HEAD@{0}: reset: moving to HEAD~2
7d3b8f1 HEAD@{1}: commit: docs: condiciones de pago
4c5e0a9 HEAD@{2}: commit: feat: plantilla de hardware

Esta red no es indefinida. La documentación oficial dice que las entradas del registro caducan: 90 días las que siguen siendo alcanzables y 30 días las que no. Después, Git las limpia de verdad.

Sirve para rescatar el error de esta semana, no para recuperar algo del año pasado. Y solo existe en tu equipo: no viaja al servidor ni al de nadie más.

El comando de cada situación

Piensa el comando antes de voltear la tarjeta.

Compruébalo tú mismo

Subiste un commit al servidor y tenía un error. ¿Qué haces?

¿Cuál es la diferencia entre reset --soft y reset --hard?

Hiciste reset --hard por error hace diez minutos. ¿Se puede recuperar?

Lo que sigue

Todo lo que llevas ocurre dentro de tu equipo y sin conexión. En la siguiente lección aparece el servidor: subir el repositorio a GitHub, bajarte lo que hicieron otros, y la parte donde se atasca casi todo el mundo la primera vez -la contraseña de la cuenta ya no sirve para esto.

Siguiente: Trabajar con GitHub

Continuar ← Ramas: probar sin romper lo que funciona