Eliminar confirmaciones de una rama en Git


3233

Me gustaría saber cómo eliminar una confirmación.

Por delete, quiero decir, es como si no hubiera hecho ese compromiso, y cuando hago un empuje en el futuro, mis cambios no se enviarán a la rama remota.

Leí git help, y creo que el comando que debería usar es git reset --hard HEAD. ¿Es esto correcto?


41
Creo que esto no es un duplicado de Git deshacer la última confirmación, ya que pregunta cómo eliminar cualquier confirmación de una rama. También creo que ninguna de las respuestas realmente aborda esta pregunta. Todos ellos rebobinar las últimas confirmaciones, no cherry-picky deleteun solo comprometen a que pueden ocurrido hace un tiempo.
Chris

12
@Chris, la respuesta git rebase -i HEAD~10responde la pregunta, ya que te permite elegir de forma arbitraria las confirmaciones para eliminar. Git aplica las confirmaciones en el rango que especifique una por una, ignorando las confirmaciones que ha eliminado del registro. Utilicé este comando hoy para deshacerme de la segunda y tercera confirmación más reciente de mi repositorio mientras mantenía la primera. Estoy de acuerdo en que ninguna de las otras respuestas son satisfactorias.
MST

@MST sí, debería haber dicho, ninguna de las opciones en la respuesta aceptada aborda esta pregunta, pero tiene toda la razón: ese comando parece funcionar
Chris

Respuestas:


4128

Cuidado: git reset --hard ELIMINARÁ SUS CAMBIOS EN EL DIRECTORIO DE TRABAJO . Asegúrese de guardar los cambios locales que desee conservar antes de ejecutar este comando.

Suponiendo que esté sentado en ese commit, entonces este comando lo activará ...

git reset --hard HEAD~1

El HEAD~1significa el compromiso antes de la cabeza.

O bien, puede mirar la salida de git log, encontrar la identificación de compromiso del compromiso al que desea hacer una copia de seguridad y luego hacer esto:

git reset --hard <sha1-commit-id>

Si ya lo presionó, deberá hacer un esfuerzo forzado para deshacerse de él ...

git push origin HEAD --force

Sin embargo , si otros pueden haberlo extraído, entonces sería mejor comenzar una nueva rama. Porque cuando tiran, simplemente lo fusionará en su trabajo, y lo volverás a empujar.

Si ya presionó, puede ser mejor usarlo git revertpara crear una confirmación de "imagen espejo" que deshacerá los cambios. Sin embargo, ambas confirmaciones estarán en el registro.


FYI - git reset --hard HEADes genial si quieres deshacerte de WORK IN PROGRESS. Lo restablecerá a la confirmación más reciente y borrará todos los cambios en su árbol de trabajo e índice.


Por último, si necesita encontrar una confirmación que "eliminó", normalmente está presente a git reflogmenos que haya recogido basura en su repositorio.


59
HEAD~1o simplemente HEAD^. Si presionó, debería usar git reverten su lugar.
Jakub Narębski

13
Obviamente, también puede usar HEAD~npara "retroceder" los ncompromisos de su cabeza. Tal vez desde este punto también se pueda interpretar ... --hard HEADcomo HEAD~0=> eliminar el trabajo en progreso.
nuala

13
@ beamrider9 imho git rebase es casi siempre la mejor manera de eliminar commits (como se describe en la respuesta de Greg Hewgill), sobre todo porque rebase de hecho incluye una gran advertencia de que eliminarás cosas 4realz.
Noah Sussman

20
Sin embargo, esto no elimina los cambios del árbol de confirmación. El OP solicitó un compromiso ya realizado. Si usted reset --hard, y verifica log --oneline --all, los commits aún permanecen en el árbol. ¿Cómo eliminamos estos commits del árbol? Gracias.
iGbanam

17
úselo reset --softpara eliminar el compromiso local ¡SIN revertir el trabajo en progreso!

704

Si aún no ha enviado el commit a ninguna parte, puede usarlo git rebase -ipara eliminar ese commit. Primero, descubra qué tan atrás está esa confirmación (aproximadamente). Entonces hazlo:

git rebase -i HEAD~N

Los ~Nmedios vuelven a redactar las últimas Nconfirmaciones ( Ndebe ser un número, por ejemplo HEAD~10). Luego, puede editar el archivo que Git le presenta para eliminar el commit ofensivo. Al guardar ese archivo, Git reescribirá todas las confirmaciones siguientes como si la que eliminó no existiera.

The Git Book tiene una buena sección sobre rebase con imágenes y ejemplos.

Sin embargo, tenga cuidado con esto, porque si cambia algo que ha presionado en otro lugar, se necesitará otro enfoque a menos que esté planeando hacer un impulso forzado.


2
Nota: Si tiene alguna fusión --no-ff en ese último lote de confirmaciones, la reorganización las eliminará :( Esto se menciona debajo de -p en esta página . El problema es que si reemplaza -i con -p, ya no aparece esa ventana emergente con las opciones para "editar este commit, sqush aquel", etc. ¿Alguien conoce la solución?
Bukov

44
¿Qué pasa si lo has empujado? (solo yo usando el repositorio remoto)
Costa

66
@Costa puede usar push -fpara forzar el empuje y reemplazar la rama remota con la local. Si es solo su propio repositorio remoto, no hay problema. El problema comienza si alguien más ha ido mientras tanto.
Greg Hewgill

3
Agregué y comprometí un archivo de datos que era demasiado grande para GitHub (sí, probablemente no debería estar en el repositorio de origen de todos modos; Oh, bueno). Cuando intenté presionar, GitHub se negó debido al archivo demasiado grande. Todo lo que quería hacer era deshacer esta confirmación, mientras guardaba algunas otras confirmaciones no relacionadas que siguieron. ¡El git rebase -i HEAD~5comando era exactamente lo que necesitaba para eliminar completamente este commit de mi repositorio local! ¡Gracias!
aldo

44
@dumbledad: con rebase -i, los cambios correspondientes a la confirmación eliminada no se conservan.
Greg Hewgill

517

Otra posibilidad es uno de mis comandos favoritos personales:

git rebase -i <commit>~1

Esto iniciará el rebase en modo interactivo -ien el punto justo antes de la confirmación que desea golpear. El editor comenzará a enumerar todas las confirmaciones desde entonces. Elimine la línea que contiene la confirmación que desea eliminar y guarde el archivo. Rebase hará el resto del trabajo, eliminando solo esa confirmación y volviendo a reproducir todos los demás en el registro.


3
gracias, por cierto, si te encuentras con algún problema (como confirmaciones vacías), puedes usarlogit rebase --continue
realgt

8
Aún más fácil: git rebase -i HEAD~1
mmell

2
Wowzers git rebase -i HEAD~1¡Realmente limpié mucho el repositorio! Es difícil decir exactamente lo que hizo, pero todo parece mucho más ordenado. Un poco alarmante, en realidad.
Charles Wood

77
Creo que vale la pena señalar que el commit no se borra, simplemente se elimina de la lista. Si comete un error , puede recuperar la confirmación utilizando el registro de ref .
Zaz

66
¿Eliminar la línea es lo mismo que d / drop?
Leo

345

Estoy agregando esta respuesta porque no veo por qué alguien que acaba de intentar comprometerse a trabajar querría eliminar todo ese trabajo debido a algún error al usar Git.

Si desea mantener su trabajo y simplemente 'deshacer' ese comando de confirmación (capturó antes de presionar para reposicionar):

git reset --soft HEAD~1

No use la bandera --hard a menos que quiera destruir su trabajo en progreso desde la última confirmación.


55
Aquí hay un ejemplo de por qué: realiza un pequeño trabajo en un servidor de desarrollo que confirma. Luego resulta que ese servidor no tiene acceso HTTPS saliente, por lo que no puede empujar el compromiso a ninguna parte. Es más fácil fingir que nunca sucedió y rehacer el parche desde su máquina local.
Steve Bennett

1
@KarthikBose siempre habrá el reflog. incluso después de que git reset --hard HEAD~1su último commit anterior esté disponible a través de reflog (hasta que caduque); ver también aquí: gitready.com/intermediate/2009/02/09/…
codeling

44
Gracias. Esta respuesta debe clasificarse más alto o incluirse en la respuesta aceptada. Eliminar un commit! = Revertir un commit.
Alsciende

2
@RandolphCarter: sin embargo, aún perderá los cambios no confirmados.
naught101

77
@Rob, un ejemplo es cuando accidentalmente confirma un archivo que contiene un secreto (por ejemplo, una contraseña) que nunca debería estar en el control de la fuente. La confirmación local debe destruirse , no solo deshacerse, por lo que nunca se enviará al servidor.
Bob Meyers

143

Eliminar una confirmación completa

git rebase -p --onto SHA^ SHA

Obviamente reemplace "SHA" con la referencia de la que desea deshacerse. La "^" en ese comando es literal.

http://sethrobertson.github.io/GitFixUm/fixup.html#change_deep


26
¿Cómo puedo votar más esta respuesta? Las otras soluciones solo muestran cómo hacerlo de forma interactiva o eliminar las confirmaciones principales.
ribamar

55
-p, --preserve-merges Recrea las confirmaciones de fusión en lugar de aplanar el historial mediante la repetición de confirmaciones que introduce una confirmación de fusión. Las resoluciones de conflicto de fusión o las enmiendas manuales para confirmar compromisos no se conservan.
raittes

55
Esta es la respuesta precisa real
Hamman Samuel

99
Dice: "reemplace SHA con la referencia de la que desea deshacerse", pero la línea tiene SHA allí dos veces. Aquí esta lo que hice. git rebase -p --onto 5ca8832c120 ^ 5ca8832c120 Pero nada cambió. ¿Se supone que debo usar el mismo SHA dos veces? Si no es así, ¿cuál es el SHA para eliminar la confirmación y cuál se supone que es el otro SHA?
Rubicksman

3
¡GUAU, funcionó a la perfección! ¡Esta debería ser la respuesta aceptada!
Liran H

51

Si no publicó los cambios, para eliminar la última confirmación, puede hacer

$ git reset --hard HEAD^

(tenga en cuenta que esto también eliminaría todos los cambios no confirmados; use con cuidado).

Si ya ha publicado commit para eliminar, use git revert

$ git revert HEAD

Eso no funcionó. Cuando git log, todo sigue ahí, no importa por qué lo hago, solo agrega más commits. Quiero limpiar la historia.
Costa

@Costa: ¿Qué no funcionó (es decir, qué versión usó) y cómo obtuvo el registro?
Jakub Narębski

He intentado casi todo en estas preguntas y respuestas. (Intenté git revert HEAD, más recientemente) Mi registro de git:tree = log --all --graph --format=format:'%C(bold blue)%h%C(reset) %C(dim black)%s%C(reset)%C(bold red)%d%C(reset) %C(green)by %an, %ar%C(reset)'
Costa

1
Solo quiero eliminar los commits (como si nunca hubieran existido). Comencé una extraña aventura de codificación, con varias nuevas confirmaciones, y todo terminó siendo basura. ¿Cómo puedo borrarlos de mi registro de git?
Costa

2
Mierda, algo mágicamente hizo exactamente lo que quería ... ¡¿Cuál de esos comandos lo hizo? !!?!
Costa

45

Digamos que queremos eliminar los commits 2 y 4 del repositorio.

commit 0 : b3d92c5
commit 1 : 2c6a45b
commit 2 : <any_hash>
commit 3 : 77b9b82
commit 4 : <any_hash>

Nota: debe tener derechos de administrador sobre el repositorio ya que está utilizando --hardy -f.

  • git checkout b3d92c5 Verifique la última confirmación utilizable.
  • git checkout -b repair Crea una nueva sucursal para trabajar.
  • git cherry-pick 77b9b82 Ejecutar a través de commit 3.
  • git cherry-pick 2c6a45b Ejecutar a través de commit 1.
  • git checkout master Checkout master.
  • git reset --hard b3d92c5 Restablezca el maestro a la última confirmación utilizable.
  • git merge repair Fusionar nuestra nueva sucursal en master.
  • git push -f origin master Empuje master al repositorio remoto.

1
el último paso debería ser que git push -f origin masterno hay opción--hard
Vivex

2
Supongo que commit 0es mayor que commit 1. Por favor, ¿podría decirme por qué primero se ejecuta commit 3(por selección de cereza) y luego por commit 1? Después de pagar b3d92cd( commit 0) esperaría una selección de cereza commit 1, entonces commit 3. Gracias.
Jarek C

@ JarekC Creo que el compromiso más importante es el compromiso más nuevo aquí, a menos que vea algo mal ...
Jeff Huijsmans

41
git reset --hard commitId

git push <origin> <branch> --force

PD: CommitId se refiere al que desea volver a


git push --force <origin> <branchName>. ya que sin mencionar el nombre de la sucursal, podría cambiar todos los archivos del control remoto.
sheelpriy

39

Cambiar con fuerza la historia

Suponiendo que no solo desea eliminar la última confirmación, sino que desea eliminar las confirmaciones específicas de las últimas n confirmaciones, vaya con:

git rebase -i HEAD~<number of commits to go back>, así que git rebase -i HEAD~5si quieres ver los últimos cinco commits.

Luego, en el editor de texto, cambie la palabra pickal droplado de cada confirmación que desee eliminar. Guarde y salga del editor. Voila!

Historial de cambios aditivos

Tratar git revert <commit hash>. Revertir creará una nueva confirmación que deshace la confirmación especificada.


dropLa palabra clave no está definida. Para eliminar una confirmación, simplemente elimine toda la línea.
Shayan Salehian

1
Para mí, drop se definió como una palabra clave, pero hacer un drop no parecía eliminar el commit del historial. Sin embargo, eliminar la línea del rebase interactivo.
Adam Parkin

Esto es exactamente lo que necesitaba. Funciona genial; ¡Gracias!
diekunstderfuge

30

Si desea arreglar su último commit, puede deshacer el commit y eliminar los archivos en él, haciendo lo siguiente:

git reset HEAD~1

Esto devolverá su repositorio a su estado antes de que git agregue comandos que organizaron los archivos. Sus cambios estarán en su directorio de trabajo. HEAD ~ 1 se refiere a la confirmación debajo de la punta actual de la rama.

Si desea liberar N commits, pero mantenga los cambios de código en su directorio de trabajo:

git reset HEAD~N

Si desea deshacerse de su último commit y no desea mantener los cambios en el código, puede hacer un restablecimiento "duro".

git reset --hard HEAD~1

Del mismo modo, si desea descartar las últimas N confirmaciones y no desea conservar los cambios de código:

git reset --hard HEAD~N

22
git rebase -i HEAD~2

Aquí '2' es el número de confirmaciones que desea rehacer.

'git rebase -i HEAD`

si quieres reajustar todos los commits.

Entonces podrá elegir una de estas opciones.

p, pick = use commit

r, reword = use commit, but edit the commit message

e, edit = use commit, but stop for amending

s, squash = use commit, but meld into previous commit

f, fixup = like "squash", but discard this commit's log message

x, exec = run command (the rest of the line) using shell

d, drop = remove commit

Estas líneas se pueden reordenar; Se ejecutan de arriba a abajo. Si elimina una línea aquí, ESTE COMITÉ SE PERDERÁ. Sin embargo, si elimina todo, se cancelará el rebase. Tenga en cuenta que las confirmaciones vacías se comentan

Simplemente puede eliminar esa confirmación utilizando la opción "d" o Eliminar una línea que tiene su confirmación.


En la última versión de git no hay más opción d . Solo necesita eliminar líneas con commits de rebase para eliminarlas.
Oleg Abrazhaev

17

Para eliminar en la sucursal local, use

git reset --hard HEAD~1

Para eliminar en una rama remota, use

git push origin HEAD --force

12

[Respuesta rápida]

Tienes muchas alternativas, por ejemplo:

  • Alternativa 1:

    git rebase -i <YourCommitId>~1
    

    Cambie YourCommitId por el número de la confirmación a la que desea volver.

  • Alternativa 2:

    git reset --hard YourCommitId
    git push <origin> <branch> --force
    

    Cambie YourCommitId por el número de la confirmación a la que desea volver.

    No recomiendo esta opción porque puede perder su trabajo en progreso.

  • Alternativa 3:

    git reset --soft HEAD~1
    

    Puede mantener su trabajo y solo deshacer el compromiso.


gracias gracias gracias (Y)
Habib Rehman

11

Fuente: https://gist.github.com/sagarjethi/c07723b2f4fa74ad8bdf229166cf79d8

Eliminar la última confirmación

Por ejemplo, tu último commit

git push origin + aa61ab32 ^: maestro

Ahora desea eliminar esta confirmación, entonces una manera fácil de hacer esto siguiente

Pasos

  1. Primero restablezca la rama al padre de la confirmación actual

  2. Empuje a la fuerza hacia el control remoto.

git reset HEAD^ --hard

git push origin -f

Para una confirmación particular, desea restablecer está siguiendo

git reset bb676878^ --hard

git push origin -f

9

Aquí hay otra forma de hacer esto:

Verifique la rama que desea revertir, luego restablezca su copia de trabajo local de nuevo a la confirmación de que desea ser la última en el servidor remoto (todo después de que se vaya adiós). Para hacer esto, en SourceTree hice clic derecho en y seleccioné "Restablecer BRANCHNAME a este commit". Creo que la línea de comando es:

git reset --hard COMMIT_ID

Como acaba de retirar su sucursal desde el control remoto, no tendrá cambios locales para preocuparse por perder. Pero esto los perdería si lo hiciera.

Luego navegue al directorio local de su repositorio y ejecute este comando:

git -c diff.mnemonicprefix=false -c core.quotepath=false \
push -v -f --tags REPOSITORY_NAME BRANCHNAME:BRANCHNAME

Esto borrará todas las confirmaciones después de la actual en su repositorio local, pero solo para esa rama.


9

El error:

I git rebase -i --root'ed mi rama, pensando ignorantemente pude reformular el primer commit que difiere del maestro (el GitHub para Windows vista predeterminada es la comparación de dominar, ocultando su totalidad).

Crecí una barba en Silicon Valley mientras más de 900 compromisos se cargaban en Sublime. Saliendo sin cambios, cargué mi batería y luego procedí a afeitarme, ya que todas las más de 900 confirmaciones individuales rebatieron indiferentemente, restableciendo sus tiempos de confirmación hasta ahora.

Determinado a vencer a Git y preservar los tiempos originales, eliminé este repositorio local y volví a clonarlo desde el control remoto.

Ahora había vuelto a agregar una confirmación de maestro innecesaria más reciente que deseaba eliminar, así que procedí así.

Agotar las opciones:

No quería git reverthacerlo, crearía una confirmación adicional, dando a Git la ventaja.

git reset --hard HEADno hizo nada, después de comprobar el reflog, el último y único HEADfue el clon: Git gana.

Para obtener el SHA más reciente, revisé el repositorio remoto en github.com: ganancia menor.

Después de pensar que git reset --hard <SHA>había funcionado, actualicé otra rama a master y 1 ... 2 ... ¡puf! el compromiso había regresado: Git gana.

Regresando al maestro, es hora de intentarlo git rebase -i <SHA>, luego elimine la línea ... en vano, es triste decirlo. " Si elimina una línea aquí, ESTE COMITÉ SE PERDERÁ ". Ah ... pasó por alto la nueva función troll n00b en las notas de la versión 2.8.3 .

La solución:

git rebase -i <SHA>entonces d, drop = remove commit.

Para verificar, verifiqué otra rama y listo, no se esconden, se comprometen a buscar / extraer del maestro.

https://twitter.com/holman/status/706006896273063936

Que tengas un buen día.


8

Todos los comandos anteriores restauran el estado de su árbol de trabajo e índice como estaban antes de realizar la confirmación, pero no restauran el estado del repositorio. Si lo miras, el commit "eliminado" no se elimina realmente, simplemente no es el que está en la punta de la rama actual.

Creo que no hay medios para eliminar un commit con comandos de porcelana . La única forma es eliminarlo del registro y volver a registrar y luego ejecutar a git prune --expire -now.


1
El orden en que se muestran las respuestas en StackOverflow no es fijo. No consulte "Todos los comandos anteriores". Haga su propia respuesta autónoma.
Pascal Cuoq

Esta respuesta no es del todo correcta. git prune es en realidad uno de los comandos de "porcelana" . Además, es raro que desee borrar por completo su registro de registro (un caso de uso es eliminar información confidencial de su repositorio, pero como dije, ese es un caso de uso raro). En la mayoría de los casos, querrá mantener las confirmaciones antiguas en el registro de registros, en caso de que necesite recuperar datos. Ver Pro Git: 9.7 Git Internals - Mantenimiento y recuperación de datos .

8

Si desea mantener el historial, mostrando la confirmación y la reversión, debe usar:

git revert GIT_COMMIT_HASH

ingrese el mensaje explicando por qué revierte y luego:

git push  

Cuando emita git log, verá los mensajes de confirmación y revertir "incorrectos".


Sí, pero el OP dejó en claro que eso no es lo que quieren.
Steve Bennett

7

Si acaba de estropear su último commit (mensaje incorrecto, olvidó agregar algunos cambios) y desea corregirlo antes de enviarlo a un repositorio público, ¿por qué no usar:

git commit --amend -m "New message here"

Si tiene cambios recién organizados, se combinarán con la última confirmación (de la que está tratando de deshacerse) y reemplazarán esa confirmación.

Por supuesto, si modifica una confirmación después de haberla presionado, está reescribiendo el historial, así que si lo hace, asegúrese de comprender las implicaciones.

También puede pasar la opción '--no-edit' en lugar de '-m' si prefiere usar el mensaje de confirmación anterior.

Documentos: http://git-scm.com/docs/git-commit.html


2
Eso no es lo que está pidiendo OP.
Steve Bennett

5

Si ya presionó, primero encuentre el commit que desea estar en HEAD ($ GIT_COMMIT_HASH_HERE) , luego ejecute lo siguiente:

git reset --hard $GIT_COMMIT_HASH_HERE
git push origin HEAD --force

Luego, en cada lugar donde se ha clonado el repositorio, ejecute:

git reset --hard origin/master

5

Lo que hago generalmente cuando me comprometo y presiono (si alguien presionó su compromiso, esto resuelve el problema):

git reset --hard HEAD~1

git push -f origin

espero que esto ayude


5

Ya he empujado. Necesito devolver algunas confirmaciones de forma remota. He intentado muchas variaciones, pero solo esto de Justin a través de git bush está funcionando bien para mí:

git reset --hard $GIT_COMMIT_HASH_HERE
git push origin HEAD --force

4

Restablecer en sucursal local

git reset --hard HEAD~<Number of commit> So git reset --hard HEAD~3

Forzar el empuje al origen

git push -f origin

3

Haga una copia de seguridad de su código en la carpeta temporal. El siguiente comando se restablecerá igual que el servidor.

git reset --hard HEAD
git clean -f
git pull

Si desea mantener sus cambios y eliminar confirmaciones recientes

git reset --soft HEAD^
git pull


2

eliminar confirmación local

Como puede ver en la imagen de arriba, quiero eliminar la confirmación de revertir "test change 2" (ID SHA1: 015b5220c50e3dfbb1063f23789d92ae1d3481a2 (puede obtener la ID SHA1 usandogitk comando en git bash)).

Para eso puedo usar (todos los comandos a continuación funcionan solo en local. Debe presionar después de eliminar):

  1. git reset --hard 515b5220c50e3dfbb1063f23789d92ae1d3481a2// te hace una copia de seguridad de ese commit (ID SHA1 del cambio de prueba 4 commit es 515b5220c50e3dfbb1063f23789d92ae1d3481a2 )
  2. git reset --hard HEAD~1 // te respalda antes de una confirmación.
  3. git reset --hard HEAD^ // Para eliminar el último commit de git

después de borrar:

después de borrar commit


2

git reset --hard HEAD~1
Estarás ahora en cabeza anterior. Tira de la rama. Empuje nuevo código. Commit se eliminará de git


A menos que ya haya presionado los cambios. En ese caso, el restablecimiento completo no limpiará su control remoto. En ese caso, rebase es la buena opción
c0der512

1

git reset --hard

git push origin HEAD --force

Si una o más de las confirmaciones están etiquetadas, elimine primero las etiquetas. De lo contrario, la confirmación etiquetada no se elimina.


0

use git revert https://git-scm.com/docs/git-revert . Revertirá todo el código, entonces puede hacer el próximo commit. Luego, la cabeza señalará ese último commit. las confirmaciones revertidas nunca se eliminan, pero no afectará su última confirmación.


0

En mi caso, mi código mágico para este pupose es este:

git reset --hard @{u}

Pruébalo y dime. He probado algunos diferentes, pero este fue el único que me ayudó.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.