Cómo eliminar permanentemente algunas confirmaciones de la rama remota

490

Sé que eso es una reescritura de la historia que es mala yada yada.

Pero, ¿cómo eliminar permanentemente algunas confirmaciones de la rama remota?

Arnis Lapsa
fuente
96
Sí, es realmente malo yada yada, pero por alguna razón necesito marcarlo como favorito.
James Morris
44
Sé que esto es estúpido, pero a veces sucede una mierda, como probar inicios de sesión y usar contraseñas de texto sin formato en su código, que son credenciales de inicio de sesión reales. Y whoops ...
frhd
66
credenciales de inicio de sesión reales ... Sí, me recuerda algunos whoopos
Hello Universe
1
Posible duplicado de las confirmaciones
wjandrea
2
Estoy tan cansado de esta discusión académica sobre lo peligroso que es esto y cómo nunca debería hacerse yada yada. Hay momentos en los que es mucho, mucho mejor eliminar cosas del historial de git y lidiar con los conflictos / rupturas de otros desarrolladores. Es realmente así de simple. Las personas que ignoran esto probablemente nunca trabajaron fuera del aula.
aplastar

Respuestas:

369

Usted git reset --hardsu sucursal local para eliminar los cambios del árbol de trabajo y el índice, y git push --forcesu sucursal local revisada al remoto. ( otra solución aquí , que implica eliminar la rama remota y volver a presionarla)

Esta respuesta SO ilustra el peligro de tal comando, especialmente si las personas dependen del historial remoto para sus propios repositorios locales. Debe
estar preparado para señalar a las personas a la sección RECUPERACIÓN DE REEMBOLSO DE UPSTREAM de la git rebasepágina del manual


Con Git 2.23 (agosto de 2019, nueve años después), usaría el nuevo comando git switch.
Es decir: (reemplazar por el número de confirmaciones para eliminar)git switch -C mybranch origin/mybranch~n
n

Eso restaurará el índice y el árbol de trabajo, como lo git reset --hardharía.

VonC
fuente
Extraño. Parece que ya lo intenté. Junto con algunos rebases, funciona como un encanto. Gracias.
Arnis Lapsa
77
@Arnis: perfecto entonces;) push --forcelejos
VonC
Utilicé BFG Repo-Cleaner para deshacerme de algunos datos confidenciales, que me dejaron con una rama "sin nombre" con el archivo original en él, después de restablecer el último commit deseado y presionar duro para el origen, todo salió bien (:
Rodrirokr
Tenga en cuenta que la URL de la confirmación aún está activa (al menos durante un tiempo), por lo que si alguien tiene la URL de la confirmación (se la dio a Dios sabe por qué), podrá acceder al código.
Mosh Feu
1
@MoshFeu True: git gcno siempre se ejecuta con la suficiente frecuencia en el lado remoto. Por ejemplo en GitHub: twitter.com/githubhelp/status/387926738161774592?lang=es
VonC
248

Solo tenga en cuenta usar el last_working_commit_id, al revertir una confirmación que no funciona

git reset --hard <last_working_commit_id>

Por lo tanto, no debemos restablecer lo commit_idque no queremos.

Entonces seguro, debemos empujar a la rama remota:

git push --force
hd84335
fuente
10
Respuesta perfecta, elegante y simple. Acabo de volver a la última confirmación de stabe que necesitaba tanto en forma remota como local
lauWM
2
Esto también me hizo perder mis cambios locales. No esperaba eso. Pero meh, mejor que comprometer tu contraseña personal para el repositorio de trabajo.
Airwavezx
3
puede guardar sus cambios locales con git stash ... haga algunas cosas ... y git stash pop (sus cambios locales están de vuelta)
MonTea
Esto me da un error como "remoto: error: denegar referencias / cabezas / maestros que no avanzan rápidamente (debe tirar primero)"
Saurabhcdt
@Airwavezx eso es lo que git reset --hardse supone que debe hacer.
Lucas
146

Importante: ¡Asegúrese de especificar qué ramas en "git push -f" o podría modificar inadvertidamente otras ramas! [*]

Hay tres opciones que se muestran en este tutorial . En caso de que el enlace se rompa, dejaré los pasos principales aquí.

  1. Revertir la confirmación completa
  2. Eliminar la última confirmación
  3. Eliminar confirmación de una lista

1 Revertir la confirmación completa

git revert dd61ab23

2 Eliminar la última confirmación

git push <<remote>> +dd61ab23^:<<BRANCH_NAME_HERE>>

o, si la sucursal está disponible localmente

git reset HEAD^ --hard
git push <<remote>> -f

donde + dd61 ... es su commit hash y git interpreta x ^ como el padre de x, y + como un forzado forzado no acelerado.

3 Eliminar el commit de una lista

git rebase -i dd61ab23^

Esto abrirá y el editor mostrará una lista de todos los commits. Elimine el que desea eliminar. Termina el rebase y empuja la fuerza al repositorio.

git rebase --continue
git push <remote_repo> <remote_branch> -f
reefaktor
fuente
55
¡Asegúrese de especificar qué ramas en "git push <remote_repo> <remote_branch> -f" o podría modificar inadvertidamente otras ramas!
Nigel Sheridan-Smith
Solo los pasos 1 y 2 hicieron el trabajo y respondieron la pregunta original. (No
ejecutes el
Estas son opciones para diferentes escenarios, no pasos a seguir. En mi caso, el rebase interactivo (Opción 3) hizo lo que estaba buscando.
Steve Blackwell
Aunque tuve que hacer el paso 3. ¿Por qué no deberías ejecutar este @Saad? Afortunadamente, mi <<remote>> era simplemente el "origen" predeterminado y <remote_branch> el "maestro" predeterminado
Bart
30

Si desea eliminar, por ejemplo, las últimas 3confirmaciones, ejecute el siguiente comando para eliminar los cambios del sistema de archivos (árbol de trabajo) y el historial de confirmaciones (índice) en su rama local:

git reset --hard HEAD~3

Luego ejecute el siguiente comando (en su máquina local) para forzar a la rama remota a reescribir su historial:

git push --force

¡Felicidades! ¡Todo listo!

Algunas notas:

Puede recuperar la identificación de confirmación deseada ejecutando

git log

A continuación, se puede reemplazar HEAD~Ncon <desired-commit-id>este aspecto:

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

Si desea mantener los cambios en el sistema de archivos y simplemente modificar el índice (historial de confirmación), use el --softindicador como git reset --soft HEAD~3. Luego tiene la oportunidad de verificar sus últimos cambios y conservarlos o soltarlos todos o parte de ellos. En el último caso, runnig git statusmuestra los archivos modificados desde entonces <desired-commit-id>. Si usa la --hardopción, git statusle indicará que su sucursal local es exactamente la misma que la remota. Si no usa --hardni --soft, se usa el modo predeterminado --mixed. En este modo, git help resetdice:

Restablece el índice pero no el árbol de trabajo (es decir, los archivos modificados se conservan pero no se marcan para confirmar) e informa lo que no se ha actualizado.

Abdollah
fuente
10

Esto podría ser demasiado poco y demasiado tarde, pero lo que me ayudó es la opción 'nuclear' que suena genial. Básicamente, utilizando el comando filter-branchpuede eliminar archivos o cambiar algo en una gran cantidad de archivos a lo largo de todo su historial de git.

Se explica mejor aquí .

jansmolders86
fuente
99
No es muy tarde Podría ser útil para los errantes con problemas similares :)
Arnis Lapsa
9

Simplificando de la respuesta de pctroll, similarmente basado en esta publicación de blog .

# look up the commit id in git log or on github, e.g. 42480f3, then do
git checkout master
git checkout your_branch
git revert 42480f3
# a text editor will open, close it with ctrl+x (editor dependent)
git push origin your_branch
# or replace origin with your remote
ted.strauss
fuente
2
Funciona para mi, gracias. Y quiero eliminar permanentemente una confirmación (por ejemplo, contiene pwd) del historial de sucursal remota, ¿cómo hago esto?
Sonríe
1
También funciona para mí, pero tengo la misma pregunta que Smiles, no quiero que nadie vea mi commit / rever en la historia ... ¿cómo elimino eso?
Roberto Rodriguez
4

A veces, la forma más fácil de solucionar este problema es crear una nueva sucursal desde el lugar donde sabe que el código es bueno. Luego puede dejar solo el historial de la rama errante en caso de que necesite seleccionar otras confirmaciones de él más adelante. Esto también asegura que no perdió ningún historial de confirmación.

Desde su sucursal local errante:

git log

copie el hash de confirmación en el que desea que esté la rama y salga del registro git

git checkout theHashYouJustCopied
git checkout -b your_new_awesome_branch

Ahora tiene una nueva sucursal tal como la desea.

Si también necesita mantener una confirmación específica de la rama errante que no está en su nueva rama, puede elegir la confirmación específica que necesita:

git checkout the_errant_branch
git log

Copie el hash de confirmación de la confirmación que necesita para ingresar en la rama buena y salir del registro git.

git checkout your_new_awesome_branch
git cherry-pick theHashYouJustCopied

Date unas palmaditas en la espalda.

Douglas.Sesar
fuente
muy fácil y a quién le importa si tienes una rama con las piernas muertas? ¡Haz una nueva sucursal y termina!
Andrew Fox
Esta es una respuesta realmente excelente. Me alegro de haber hecho esto en lugar de elegir commits o manipular la rama remota.
Magnilex
0
 git reset --soft commit_id
 git stash save "message"
 git reset --hard commit_id
 git stash apply stash stash@{0}
 git push --force
pandorago
fuente