¿Cómo elimino los commits de git no apresurados?

948

Accidentalmente me comprometí con la rama equivocada. ¿Cómo elimino esa confirmación?

NullVoxPopuli
fuente

Respuestas:

1811

Elimina la confirmación más reciente y conserva el trabajo que has realizado:

git reset --soft HEAD~1

Elimine la confirmación más reciente, destruyendo el trabajo que ha realizado:

git reset --hard HEAD~1
dbyrne
fuente
13
asegúrese de que HEAD esté apuntando a la rama ... (compruébelo primero)
Frank Schwieterman
128
Y asegúrese de que HEAD ~ 1 sea el commit ... También podría hacerlogit reset --hard origin
Daenyth
13
El pensamiento git remoteenumera el origen para mí, git reset --hard origindice fatal: ambiguous argument 'origin': unknown revision or path not in the working tree.. ¿Por qué?
trss
77
Esto es asombroso Acabo de salvar mi vida.
NinjaBoy
2
git reset HEAD~1también mantendrá todos sus cambios, pero lo dejará con un índice vacío en lugar de mantener todo (como lo --softharía la opción).
Holloway
139

Me pregunto por qué la mejor respuesta que he encontrado es solo en los comentarios. ( por Daenyth con 86 votos )

git reset --hard origin

Este comando sincronizará el repositorio local con el repositorio remoto eliminando cada cambio que haya realizado en su local. También puede hacer lo siguiente para obtener la rama exacta que tiene en el origen.

git reset --hard origin/<branch>
Ashkan Sirous
fuente
16
Gracias por esto, ampliando la explicación ligeramente: para una rama específica:git reset --hard origin/<branch>
claro
44
O git reset --soft origin/<branch>, si desea deshacerse del compromiso pero mantener el trabajo local.
riverhorse
1
entiendo fatal: ambiguous argument 'origin': unknown revision or path not in the working tree., debes especificar la rama como:git reset --hard origin/feature/my-cool-stuff
Kip
¡Brillante! Esto realmente funciona, a diferencia de la respuesta "aceptada" que simplemente separa la cabeza y te deja colgado.
mae
55

No lo elimine: solo una confirmación git cherry-pickes suficiente.

Pero si tuvo varias confirmaciones en la rama incorrecta, ahí es donde git rebase --ontobrilla:

Supongamos que tienes esto:

 x--x--x--x <-- master
           \
            -y--y--m--m <- y branch, with commits which should have been on master

, entonces puedes marcarlo mastery moverlo donde quieras estar:

 git checkout master
 git branch tmp
 git checkout y
 git branch -f master

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- y branch, master branch

, restablecer y bifurcar donde debería haber estado:

 git checkout y
 git reset --hard HEAD~2 # ~1 in your case, 
                         # or ~n, n = number of commits to cancel

 x--x--x--x <-- tmp
           \
            -y--y--m--m <- master branch
                ^
                |
                -- y branch

y, finalmente, mueva sus confirmaciones (vuelva a aplicarlas, haciendo nuevas confirmaciones)

 git rebase --onto tmp y master
 git branch -D tmp


 x--x--x--x--m'--m' <-- master
           \
            -y--y <- y branch
VonC
fuente
desafortunadamente, esa no era la pregunta.
KatariaA
1
@KatariaA Esa es una alternativa válida a la eliminación de la confirmación realizada en la rama incorrecta y ayudará a otros en la misma situación (buena confirmación realizada en la rama incorrecta).
VonC
14

Haz un git rebase -i FAR_ENOUGH_BACKy suelta la línea para el commit que no quieres.

Hank Gay
fuente
6

Si desea mover ese compromiso a otra rama, obtenga el SHA del compromiso en cuestión

git rev-parse HEAD

Luego cambie la rama actual

git checkout other-branch

Y cherry-pickel compromiso deother-branch

git cherry-pick <sha-of-the-commit>
Alexander Groß
fuente
Desde mi experiencia, esto no deshace el commit de la rama original, por lo que es necesario el git reset --hard HEAD~1posterior. Creo que usar reset --softluego cambiar de rama y comprometerse nuevamente habría ahorrado trabajo extra. Por otra parte, estaba usando SourceTree para hacer la mayoría de mis cosas básicas, solo ordenando alinearlo con esto después de mi error.
jusopi
3

Para su referencia, creo que puede hacer "hard cut" los compromisos de su rama actual no solo con git reset --hard, sino también con el siguiente comando:

git checkout -B <branch-name> <SHA>

De hecho, si no le importa pagar, puede configurar la rama a lo que quiera con:

git branch -f <branch-name> <SHA>

Esta sería una forma programática de eliminar confirmaciones de una rama, por ejemplo, para copiar nuevas confirmaciones (usando rebase).

Suponga que tiene una rama que está desconectada del maestro porque ha tomado fuentes de otra ubicación y la ha vertido en la rama.

Ahora tiene una rama en la que ha aplicado cambios, llamémosle "tema".

Ahora creará un duplicado de la rama de su tema y luego lo volverá a basar en el volcado del código fuente que se encuentra en la rama "volcado":

git branch topic_duplicate topic
git rebase --onto dump master topic_duplicate

Ahora sus cambios se vuelven a aplicar en la rama topic_duplicate en función del punto de partida de "dump", pero solo las confirmaciones que se han producido desde "master". Por lo tanto, sus cambios desde el maestro ahora se vuelven a aplicar sobre "dump", pero el resultado termina en "topic_duplicate".

Luego puede reemplazar "dump" con "topic_duplicate" haciendo lo siguiente:

git branch -f dump topic_duplicate
git branch -D topic_duplicate

O con

git branch -M topic_duplicate dump

O simplemente descartando el basurero

git branch -D dump

Quizás también podría elegir simplemente después de borrar el "topic_duplicate" actual.

Lo que estoy tratando de decir es que si desea actualizar la rama "duplicada" actual basada en un antepasado diferente, primero debe eliminar los commits "cherrypicked" anteriores haciendo un git reset --hard <last-commit-to-retain>o git branch -f topic_duplicate <last-commit-to-retain>y luego copiando los otros commits (desde el main rama temática) ya sea mediante rebase o selección de cerezas.

Rebasing solo funciona en una rama que ya tiene los commits, por lo que debe duplicar su rama de tema cada vez que quiera hacer eso.

Cherrypicking es mucho más fácil:

git cherry-pick master..topic

Entonces toda la secuencia se reducirá a:

git reset --hard <latest-commit-to-keep>
git cherry-pick master..topic

Cuando se ha desprotegido su rama duplicada de tema. Eso eliminaría las confirmaciones previamente seleccionadas del duplicado actual y simplemente volvería a aplicar todos los cambios que ocurran en el "tema" en la parte superior de su "volcado" actual (antepasado diferente). Parece una forma razonablemente conveniente de basar su desarrollo en el maestro ascendente "real" mientras usa un maestro "descendente" diferente para verificar si sus cambios locales también se aplican a eso. Alternativamente, podría generar un diff y luego aplicarlo fuera de cualquier árbol fuente de Git. Pero de esta manera puede mantener una versión actualizada (parcheada) modificada que se basa en la versión de su distribución mientras su desarrollo real está en contra del maestro principal real.

Tan solo para demostrar:

  • restablecer hará que su rama apunte a una confirmación diferente (--hard también verifica la confirmación anterior, --soft mantiene los archivos agregados en el índice (que se confirmaría si se confirma de nuevo) y el valor predeterminado (--mixed) no revisa el commit anterior (borrando tus cambios locales) pero borrará el índice (todavía no se ha agregado nada para commit)
  • puedes forzar a una rama a que apunte a una confirmación diferente
  • puedes hacerlo mientras revisas inmediatamente ese commit también
  • rebase funciona en commits presentes en su rama actual
  • recoger cerezas significa copiar desde una rama diferente

Espero que esto ayude a alguien. Tenía la intención de reescribir esto, pero no puedo hacerlo ahora. Saludos.

Xennex81
fuente
0

El siguiente comando funcionó para mí, todos los cambios comprometidos locales se descartan y el local se restablece al mismo que el origen remoto / rama maestra.

git reset - origen duro

Atul Sureka
fuente