¿Hay alguna forma de deshacer git push -f?

Si uso push -f para superponer el último commit, es decir, A, en el repository remoto, y otros han sacado A antes de presionar.

De todos modos para deshacer esto en caso de no causar problemas para los demás?

¿Es útil push -f original para " pretender " que nada ha sido tocado?

O

¿Cómo decide Git si el repository local diverge del seguimiento remoto?

Hay algunas maneras de descubrir el HEAD original antes del push (ORIG_HEAD probablemente no sea uno de ellos):

Desplazamiento de la terminal

Si tiene la suerte de tener la terminal abierta, habrá alguna salida cuando se hizo la inserción que se ve así:

 ... To user@host:repo.git + abcdef0...1234567 HEAD -> branchname (forced update) 

Aquí, abcdef0 era el HEAD anterior (su A ) y 1234567 era lo que lo obligó a ser en su lugar.

git reflog

La salida de git reflog te dice la historia cronológica de lo que hiciste. Básicamente, desea volver a la línea en cuestión (donde había revisado su sucursal antes de los cambios) y tomar la ID de confirmación de la primera columna.

El command más útil aquí es git reflog show remotes/origin/branchname . Esto debería mostrarle su actualización forzada ( 1234567 ) y la identificación de confirmación anterior ( abcdef0 ) como las dos líneas superiores.

Referencia anterior

Un par de references de compromiso pueden ser útiles aquí:

  • @{1} (o nombre de branchname@{1} , si no está en esa twig) es el valor anterior de esa reference. Solo funciona si no ha realizado ningún otro commit en su sucursal local.
  • De manera similar, los remotes/origin/branchname@{1} serán el valor previo de la reference en el control remoto. Solo funciona si alguien más no ha empujado al control remoto.

Verificando que tienes la identificación correcta

Si desea confirmar que la identificación que ha obtenido de uno de los methods anteriores es correcta, simplemente compruébelo:

 git checkout abcdef0 

y mira alnetworkingedor Si el git log parece familiar (también recomiendo tig para explorar su repository, e incluso puede ejecutar tig abcdef0 para ver el logging de una confirmación determinada), entonces puede estar seguro de que está restableciendo en el lugar correcto.

Restablecimiento al estado anterior

Una vez que tenga la identificación de confirmación anterior, puede restablecerla y forzar la inserción nuevamente:

 git checkout branchname # if you're not on it already git reset --hard abcdef0 git push -f 

o solo:

 git push -f origin abcdef0:branchname 

Esto restaurará el estado de la bifurcación al estado anterior al empuje forzado.

¿Cuál es el impacto?

Si la gente ha tirado de la twig desde que empujó la fuerza, si tuviera que forzar el retroceso al original, entonces se encontrarán con problemas al actualizarse posteriormente. Si no se han comprometido con esa sucursal, pueden simplemente eliminar su sucursal local y volver a realizar el checkout (después de una git fetch para asegurarse de que tengan references actualizadas), o lo siguiente hará lo mismo:

 git fetch git checkout branchname # if you're not on it already git reset --hard origin/branchname 

Si han realizado confirmaciones locales, necesitarán volver a establecer esos cambios en el historial correcto (y posiblemente resolver cualquier conflicto):

 git fetch git checkout branchname # if you're not on it already git rebase --onto origin/branchname 1234567 

Lo anterior significa "reproducir todos los commits después de 1234567 (la cabeza incorrecta) en la parte superior de origin/branchname (la cabeza correcta)".