¿Cómo deshacer las confirmaciones locales más recientes?

Accidentalmente confirmé los archivos incorrectos en Git, pero aun no he precionado la confirmación hacia el servidor.

¿Cómo puedo deshacer aquellas confirmaciones desde el repositorio local?

  • git
  • version-control
  • git-commit
  • undo
7 Repuestas

Deshacer una confirmación y rehacerla

$ git commit -m "Algo terriblemente mal guiado" # (1)
$ git reset HEAD~                               # (2)
<< editar archivos según sea necesario >>	# (3)
$ git add ...                                   # (4)
$ git commit -c ORIG_HEAD                       # (5)

  1. Esto es lo que quieres hacer.
  2. Esto deja a tu árbol de trabajo (el estado de tus archivos en el disco) sin alteraciones pero deshace la confirmación sin etapas (por eso apareceran como "Cambios sin alteraciones para confirmaciones" en git status, para eso necesitarás agregarlas nuevamente antes de confirmar). Si solamente quieres agregar más cambios a las confirmaciones previas o cambiar el mensaje de confirmacion1 podrías usar esto git reset --soft HEAD~ en vez del cual que es como git reset HEAD~ (donde HEAD~ es la misma HEAD~1) pero deja tus cambios existentes escenificados.
  3. Haz correciones a los archivos del árbol de trabajo.
  4. git add cualquier cosa que quieras incluir en tu nueva cofimación.
  5. Confirma los cambios reusando el antiguo mensaje de confirmación. reset al restablecer el copiado del antiguo encabezado a .git/ORIG_HEAD ; commit con -c ORIG_HEAD se abrirá un editor, el cual contiene inicialmente el mensaje de registro de la antigua confirmación y te permitirá editarlo. Si no necesitas editar el mensaje podrías usar la opción -C.

Sin embargo, si has adherido algun cambio nuevo al indice, debes tener cuidado ya que commit --ammend agregará tus confirmaciones previas.

Si el codigo ya esta insertado en tu servidor y ya tienes los permisos para sobrescribir el historial (rebase) entonces:

git push origin master --force

También puedes ver esta respuesta en:

Como mover HEAD a una ubicación anterior (encabezado separado) & Deshacer confirmaciónes

La respuesta anterior te mostrará git reflog la que se usa para averiguar que es el SHA-1 la cual es la que deseas revertir. Una vez que hayas encontrado el punto que deseas deshacer para usar la secuencia de comandos explicada anteriormente.


1 Sin embargo debes tener en en cuenta, que no necesitas reestablecer a una confirmación anterior si solamente comestiste un error. En tu mensaje de confirmación la opción más fácil es git reset (para elimiar cualquier cambio que hayas ralizado desde) y entonces git commit --amend, el cual abrirá el editor de mensaje de confirmación por defecto rellenado anteriormente con el ultimo mensaje de confirmación.

Deshacer una confirmación da un poco de miedo si no sabes como funciona. Pero de hecho es increiblemente fácil si lo entiendes.

Di que tienes esto, donde esta C es tu HEAD y (F) es el estado de tus archivos.

   (F)
A-B-C
    ↑
  master

Tu quieres que nuke confirme a C y nunca volverlo a ver. Tienes que hacer esto:

git reset --hard HEAD~1

El resultado será

 (F)
A-B
  ↑
master

Ahora B es HEAD. Como usaste --hard tus archivos son reestablecidos a su estado de confirmación B.

Ah, pero supone que la confirmación V no fue tan grave. Debes deshacer la confirmación pero mantener tus cambios para editar un poco antes de hacer una mejor confirmación. Comienza nuevamente aqui, con C como tu HEAD:

   (F)
A-B-C
    ↑
  master

Puedes hacer esto dejando fuera a --hard:

git reset HEAD~1

En este caso el resultado es:

   (F)
A-B-C
  ↑
master

En ambos casos, HEAD es solo un indicador a la última confirmación. Cuando hagas un git reset HEAD~1, le diras a Git que mueva el indicador HEAD y vuelva un indicador pero (al menos que uses --hard) dejaras los archivos como estaban. Entonces ahora git status muestra los cambios que habías registrado C. ¡No habrás perdido nada!

Para un toque más ligero incluso puedes deshacer tu confirmación pero dejar tus archivos y tu índice:

git reset --soft HEAD~1

Esto no solo deja tus archivos solos si no que incluso también deja tu índice solo. Cuando haces git status, verás que los mismos archivos están en el índice como antes. De hecho, justo despues de este comando podrías hacer git commit y estarías rehaciendo la misma confirmación que ya habias hecho.

Una cosa mas. Supone que borras una confirmación como en el primer ejemplo, pero luego descubres que la necesitas. Mala suerte, verdad?

No, aun existe una manera de recuperarla git reflog y verás una lista (parciale) de confirmaciones shas (esto es hashes) esn los cuales te has movido. Busca la confirmación que destruiste y haz lo siguiente:

git checkout -b someNewBranchName shaYouDestroyed

Ahora ya has resucitado esa confirmación. En realidad las confirmaciones no se destruyen en Git por alrededor de 90 días, por eso normalmente puedes volver y rescatar alguna de la cual no hayas querido desahacerte.

Esto me llevo algún tiempo descubrirlo, por eso capaz que podria ayudar a alguien...

Hay dos maneras de "deshacer" tu última confirmación, dependiendo de si ya has hecho tu confirmación pública (enviado a tu repositorio remoto):

Cómo deshacer una confirmación local

Digamos que he confirmado localmente pero ahora quiero hacerla remota.

git log
    commit 101: confirmacion mal    # Último confirmación, esto se llamaría 'HEAD'.
    commit 100: confirmacion bueno  # Segundo al último confirmación, este es el que queremos.

Para restaurar todo a la manera anterior a la última confirmación, necesitamos: reset hacia la confirmación antes HEAD:

git reset --soft HEAD^     # usa --soft si quieres mantener tus cambios
git reset --hard HEAD^     # use - hard si no le importa mantener los cambios que hizo

Ahora git log mostrará que tu última confirmación ha sido removida.

Cómo rehacer una confirmación pública

Si ya has hecho tu confirmación pública, vas a querer crear una nueva confirmación la cual "revertirá" los cambios que has hecho en tu confirmación previa. (HEAD actual)

git revert HEAD

Ahora tus cambios serán revertidos y estarán listos para tu confirmación.

Para mas información verifica en Git Basics - Undoing Things.

Agregar/quitar archivos para conseguir cosas de la manera que quieras:

git rm classdir
git add sourcedir

Luego enmendra el compromiso:

git commit --amend

La confirmacion erronea previa será editada para reflejar el nuevo estado del índice - en otras palabras, esto será como si nunca hubieras cometido el error en primer lugar.

Ten en cuenta que solo deberás hacer esto si no los has enviado todavia. Si ya los has enviado, solo tendrás que confirmar un arreglo normalmente.

git rm yourfiles/*.class
git commit -a -m "borró todos los archivos de clase en la carpeta 'yourfiles'"

o

git reset --hard HEAD~1

Preacución: El comando mensionado quitará permanentemente las modificaciones a los archivos .java (y a cualquier otro archivo) que quiras confirmar.

El reinicio completo estable cerá tu copia de trabajo en el estado de la confirmación antes de cometer errores en una confirmación erronea.

Cambiar la última confirmación

Remplazar los archivos en el índice:

git rm --cached *.class
git add *.java

Si se trata de una rama privada, modifica la confirmación:

git commit --amend

O, si es una rama compartida haz una nueva confirmación:

git commit -m 'Reemplace los archivos .class con archivos .java'

(Para cambiar a una previa confirmación usa el increible interactive rebase.)

ProTip™: Agrega *.class a un gitignore para evitar que esto ocurra nuevamente.


Revertir una confirmación

Enmendar una confirmación es la solución ideal si necesitas cambiar la última confirmación, pero una solución más general es reset.

Puedes restablecer git a cualquier confirmación con:

git reset @~N

Donde N es el numero de confirmaciones antes HEAD, y @~ restablece a la confirmación anterior.

Por eso en vez de enmendar la confirmación, podrias usar:

git reset @~
git add *.java
git commit -m "Añadir archivos .java"

Verifica git help reset, especificamente la seccion de --soft, -mixed y --hard, para un mejor entendimiento de lo que esto hace.

Reflog

Si te equivocas siempre puedes usar reflog para encontrar caonfirmaciones caidas.

$ git reset @~
$ git reflog
c4f708b HEAD@{0}: reset: pasando a @~
2c52489 HEAD@{1}: commit: añadido algunos archivos .class
$ git reset 2c52489
... y estás de vuelta donde empezaste

Zaz

Usa git revert <confirmación-id>

Para conseguir la ID de confirmación solo usa git log.