Revertir el repositorio git local y remoto en 1 commit

188

He leído publicaciones similares sobre este tema, y ​​no puedo entender cómo hacerlo correctamente.

Registré alrededor de 1000 archivos que no quiero, y prefiero no tener que pasar por 1by1 y eliminarlos todos del repositorio.

  • Tengo una mastersucursal remota .
  • Tengo la mastersucursal local .

Ambos están en la misma revisión.

Quiero revertir mi control remoto en 1 commit.

Digamos que mi historia masteres A--B--C--D--E.
Quiero revertir mi local a D.
Luego empújelo a remoto para que mi hash actual sea D remoto y local.

Tengo problemas para hacer esto.
Estoy usando Git Tower pero me siento cómodo con la línea de comando. ¿Alguna ayuda?

ACTUALIZACIÓN: Grandes comentarios a continuación. El uso de un reinicio parece estar parcialmente desaconsejado, especialmente si el repositorio se comparte con otros usuarios. ¿Cuál es la mejor manera de deshacer los cambios del commit anterior sin usar un restablecimiento completo ? ¿Hay alguna manera?

Jamis Charles
fuente
He actualizado mi respuesta para "deshacer los cambios del commit anterior sin usar un restablecimiento completo".
VonC
3
Úselo git revertpara hacer sin restablecimientos duros y sin molestar a los usuarios.
user562374
2
Posible duplicado de las confirmaciones
wjandrea
Retroceder el control remoto es lo que se desaconseja, pero si eso es lo que desea hacer, hágalo. Hay cientos de formas de hacerlo, pero el resultado sería el mismo en el lado del servidor.
FelipeC

Respuestas:

307

Si nadie ha retirado su repositorio remoto todavía, puede cambiar el HEAD de su rama y forzarlo a dicho repositorio remoto:

git reset --hard HEAD^ 
git push -f 

(o, si tiene acceso directo al repositorio remoto, puede cambiar su referencia HEAD aunque sea un repositorio simple )

Tenga en cuenta que, como comenta la tecnología alienígena en los comentarios a continuación , en Windows (sesión CMD), necesitaría ^^:

git reset --hard HEAD^^
git push -f 

Actualización desde 2011:
Usar git push --force-with-lease( que presento aquí , presentado en 2013 con Git 1.8.5) es más seguro.

Vea la respuesta de Schwern como ilustración.


¿Qué pasa si alguien ya ha retirado el repositorio? ¿Qué haría yo entonces?

Entonces sugeriría algo que no reescribe la historia:

  • git revert localmente su último commit (creando un nuevo commit que revierte lo que hizo el commit anterior)
  • empujar el 'revertir' generado por git revert.
VonC
fuente
1
¿Qué pasa si alguien ya ha retirado el repositorio? ¿Qué haría yo entonces?
Jamis Charles
1
@gwho crea una rama? No, mueve la CABEZA de una rama, pero todavía estás en la misma rama. Sin embargo, dado que el empuje ya no es un avance rápido, sí, debe forzar ese empuje.
VonC 01 de
1
¿Hay alguna manera de saber si alguien ha retirado el repositorio?
Pinkerton
44
En Windows, el carácter ^ se usa para la continuación de línea y para escapar de un carácter, haciendo que el comando: git reset --hard HEAD ^^
Alien Technology
1
@AlienTechnology Usando Powershell, en Windows 10, solo tuve que escribir reset --hard HEAD^y no reset --hard HEAD^^restablecer el último commit.
Gaspacchio
58

Establezca la rama local una revisión hacia atrás ( HEAD^significa una revisión hacia atrás):

git reset --hard HEAD^

Empuje los cambios al origen:

git push --force

Tendrás que forzar a empujar porque de lo contrario git reconocería que estás detrás origin por un compromiso y nada cambiará.

Al hacerlo, --forcele dice a git que sobrescriba HEADen el repositorio remoto sin respetar ningún avance allí.

Eckes
fuente
1
Sugeriría no llamar a esto una reversión, ya que es un término específico con un significado muy diferente en git.
Cascabel
@Jefromi: Gracias por la pista. Editado
Eckes
Gran respuesta. He leído que el uso de un reinicio parece estar parcialmente desaconsejado, especialmente si el repositorio se comparte con otros usuarios. ¿Hay una forma más limpia de hacer esto, que deshaga todos los cambios de su confirmación anterior?
Jamis Charles
¡Ten cuidado! Guarda tus cambios no comprometidos o los has perdido
Nosov Pavel
Eso es genial. Entonces, ¿esto significa que cuando lo hagamos git push origin master, Git puede crear una nueva confirmación en el control remoto porque la rama local está adelante al menos una vez? Además, este último debe ser sustancialmente diferente de lo que apunta la cabeza en el repositorio remoto.
MadPhysicist
18

Si desea revertir la última confirmación, escuche:

Paso 1:

Verifique sus confirmaciones locales con mensajes

$ git log

Paso 2:

Elimine la última confirmación sin restablecer los cambios desde la rama local (o maestra)

$ git reset HEAD^

O si no desea escuchar los últimos archivos de confirmación y actualizaciones

$ git reset HEAD^ --hard

Paso 3:

Podemos actualizar los archivos y códigos y nuevamente necesitamos presionar con fuerza para que elimine el commit anterior. Mantendrá un nuevo compromiso.

$ git push origin branch -f

¡Eso es!

Kannan S
fuente
Eso no revierte un commit, está reemplazando uno. Por favor, no nos confunda git novicios haciendo un mal uso de los términos convencionales.
Suncat2000
7

Al ingresar el siguiente comando, puede ver su historial de confirmación de git:

$ git log

Digamos que su historial en esa rama en particular es como: commit_A, commit_B, commit_C, commit_D. Donde, commit_D es el último commit y aquí es donde queda HEAD. Ahora, para eliminar su último commit de local y remoto, debe hacer lo siguiente:

Paso 1: eliminar el último compromiso localmente mediante:

$ git reset --DUR HEAD ~

Esto cambiará su commit HEAD a commit_C

Paso 2: Empuje su cambio para el nuevo HEAD commit to remote

$ git push origin + HEAD

Este comando eliminará la última confirmación del control remoto.

PD: este comando se prueba en Mac OSX y también debería funcionar en otros sistemas operativos (sin embargo, no reclama sobre otros sistemas operativos)

sahilabrar
fuente
3

Para máquinas con Windows, use:

git reset HEAD~1  #Remove Commit Locally
Anvesh Yalamarthy
fuente
3

Aquí hay una versión actualizada del procedimiento que es más segura.

git reset --hard HEAD^ 
git push --force-with-lease

git push -freemplazará indiscriminadamente el repositorio remoto con sus propios cambios. Si alguien más ha presionado los cambios, se perderán.git push --force-with-leasesolo empujará su rebase si el repositorio es como espera. Si alguien más ya ha presionado, su impulso fallará.

Ver –fuerza considerada dañina; entendiendo git's –force-with-lease .

Recomiendo alias esto como repush = push --force-with-lease.

¿Qué pasa si alguien ya ha retirado el repositorio? ¿Qué haría yo entonces?

Diles que lo hagan git pull --rebase=merges. En lugar de a git fetch originy git merge origin/masterlo hará git fetch originy git rebase -r origin/master. Esto reescribirá cualquiera de sus cambios locales masteren la parte superior del nuevo rebase origin/master. -rpreservará cualquier fusión que puedan haber hecho.

Recomiendo que este sea el comportamiento predeterminado para tirar. Es seguro, manejará los rebases de otros y resulta en fusiones menos innecesarias.

[pull]
        rebase = merges
Schwern
fuente
1
De acuerdo y votado. En mi defensa, mi vieja respuesta de 2011 fue escrita dos años antes de la introducción de la --force-with-leaseopción.
VonC
Pensé que ya lo hice (ayer): stackoverflow.com/posts/4647362/revisions
VonC
1

Resolví problemas como el tuyo con estos comandos:

git reset --hard HEAD^
git push -f <remote> <local branch>:<remote branch> 
Ibrohim Ermatov
fuente
0

Solo quería eliminar el último commit del historial de commit remoto y claro también. Lo siguiente funcionó a las mil maravillas

git reset --hard HEAD^ 
git push -f 
minhas23
fuente
Pero, ¿cómo "lo siguiente" es diferente de mi respuesta anterior ?
VonC
0

La forma de restablecer la cabeza y revertir la confirmación anterior es a través de

$ git reset HEAD^ --hard
$ git push <branchname> -f

Pero a veces puede no ser aceptado en la rama remota:

To ssh:<git repo>
 ! [rejected]        develop -> develop (non-fast-forward)
error: failed to push some refs to 'ssh:<git repo>'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

entonces la otra forma de hacerlo es

git revert HEAD
git push <remote branch>

Esto funciona bien

NOTA: recuerde si git push -f <force>falló y luego intenta revertir. Haga un git pullantes, de modo que lo remoto y lo local estén sincronizados y luego intente git revert.
Verifique git logpara asegurarse de que el control remoto y el local estén en el mismo punto de confirmación con el mismo SHA1.

git revert 
A --> B --> C -->D
A--> B --> C --> D --> ^D(taking out the changes and committing reverted diffs)
ravi.zombie
fuente
0

en maestro local

git reflog
-- this will list all last commit
  e.g Head@{0} -- wrong push
      Head@{1} -- correct push  
git checkout Head@{1} .
  -- this will reset your last modified files

git status 
git commit -m "reverted to last best"
git push origin/master

No hay que preocuparse si otro ha tirado o no.

¡Hecho!

Bhushan
fuente
0

Si solo desea eliminar la última confirmación del repositorio remoto sin desordenar su repositorio local, aquí hay una línea:

git push origin +origin/master~:master

Utiliza la siguiente sintaxis:

git push <remote> <refspec>

Aquí, <remote>es originy <refspec>tiene la siguiente estructura:

+origin/master~:master

Los detalles se pueden encontrar en git-push(1). Lo anterior +significa "forzar a empujar esta referencia", y la otra parte significa "de origin/master~a master(de remoto origin)". No es difícil saber que origin/master~es el último commit antes origin/master, ¿verdad?

iBug
fuente
0

para mí funciona estos dos comandos:

git checkout commit_id
git push origin +name_of_branch
Yahor M
fuente
0

También puedes hacer esto:

git reset --hard <commit-hash>
git push -f origin master

y que todos los demás que obtuvieron los últimos commits malos se restablezcan:

git reset --hard origin/master
A-Sharabiani
fuente