¿Cómo puedo recuperarme de un git push -f origin master erróneo?

93

Acabo de enviar la fuente incorrecta a mi proyecto usando la --forceopción.

¿Es posible revertir? Entiendo que todas las ramas anteriores se han sobrescrito con la -fopción, por lo que es posible que haya arruinado mis revisiones anteriores.

David van Dugteren
fuente
posible duplicado de ¿Hay alguna forma de deshacer git push -f?
cmbuckley

Respuestas:

55

Git generalmente no tira nada, pero recuperarse de esto puede ser complicado.

Si tiene la fuente correcta, puede presionarla en el control remoto con la --forceopción. Git no habrá eliminado ninguna rama a menos que usted se lo indique. Si realmente ha perdido confirmaciones, eche un vistazo a esta guía útil para recuperar confirmaciones . Si conoce el SHA-1 de las confirmaciones que desea, probablemente esté bien.

Lo mejor que puede hacer: haga una copia de seguridad de todo y vea lo que todavía hay en su repositorio local. Haga lo mismo en el control remoto si es posible. Úselo git fsckpara ver si puede recuperar cosas y, sobre todo, NO ejecutargit gc .

Sobre todo, nunca use la --forceopción a menos que realmente lo diga en serio.

Cameron Skinner
fuente
64
Es muy probable que pueda mirar los reflogs para determinar dónde estaban originalmente las sucursales remotas. Por ejemplo git reflog show remotes/origin/master,. Debería poder ver su empuje allí; el compromiso en la línea anterior es donde estaba antes de que lo arruinaras. A continuación, puede enviar esa revisión (con --force) al origen y volver a donde estaba.
Cascabel
@David: Oh. No mencionaste en tu pregunta que no tenías el repositorio. (Esto es, por supuesto, algo que nunca querrá hacer). Sin embargo, si tiene acceso al sistema de archivos donde presionó, aún puede hacer todo esto allí.
Cascabel
1
@David: ¡Ay! Siempre es bueno tener su directorio actual como parte de su mensaje para evitar ese tipo de cosas.
Cascabel
1
@Jefromi Creo que lo que dijiste es la respuesta real: ¡incluso con una versión anterior (sin haber git fetcheditado durante mucho tiempo) puedes mostrar el reflog del lado de GitHub y recuperarte!
NH2
1
¿Dónde está esta respuesta de @Jefromi? No veo a ese usuario mencionado en esta página fuera de este hilo de comentarios.
Don McCurdy
47

Si conoce el hash de confirmación, es fácil, simplemente vuelva a crear su rama.

5794458...b459f069 master -> master (forced update)

Eliminar la rama remota:

git push origin :master

luego vuelva a crear su rama con los siguientes comandos:

git checkout 5794458
git branch master
git push origin master
usuario1094125
fuente
28

La solución ya se menciona aquí.

# work on local master
git checkout master

# reset to the previous state of origin/master, as recorded by reflog
git reset --hard origin/master@{1}

# at this point verify that this is indeed the desired commit.
# (if necessary, use git reflog to find the right one, and
# git reset --hard to that one)

# finally, push the master branch (and only the master branch) to the server
git push -f origin master
Abdelhafid
fuente
Gracias, esto funcionó para mí. No tuve acceso para eliminar el maestro, por lo que el comentario aprobado falló.
Andi
Sí, y git reflog show remotes/origin/mastersi es necesario git reflog (como lo menciona @Cascabel arriba)
Josiah Yoder
2
Esta es la respuesta correcta, gracias por vincular a la correcta.
Noitidart
6

Si no se encuentra en ese repositorio local de donde provino el empuje forzado, a nivel de origen / maestro no hay forma de recuperarse. Pero si tiene la suerte de utilizar GitHub o GitHub para empresas , puede echar un vistazo a la API REST y recuperar la confirmación perdida como parche, por ejemplo:

  1. Enumere eventos y encuentre el formato largo de confirmación sha1

https://api.github.com/repos/apache/logging-log4j2/events

  1. Descargue la confirmación perdida y recupere el parche relacionado en la ruta json .files [] / patch

https://api.github.com/repos/apache/logging-log4j2/commits/889232e28f3863d2a17392c06c1dd8cac68485de

  1. Aplicar localmente y presionar nuevamente

git apply patch.patch && git commit -m "compromiso restaurado" && git push origin master

Pierrick HYMBERT
fuente
4

Otra forma de recuperar la confirmación perdida o incluso de averiguar qué confirmaciones se perdieron, si la inserción anterior no vino de su repositorio local, es mirar su máquina de CI.

Si tiene un trabajo que prueba la rama maestra después de cada confirmación (o serie de confirmaciones consecutivas), que debería tener, puede echar un vistazo a lo que estaba probando por última vez. Ese es el compromiso que necesita restaurar.

La máquina de CI puede incluso mantener un clon local del repositorio, desde el cual es posible que pueda realizar esta recuperación.

Fuente: probablemente Entrega continua: Versiones de software confiables a través de la automatización de compilación, prueba e implementación (Addison-Wesley Signature Series (Fowler))

user7610
fuente
3

Sí, puedes recuperar confirmaciones después git push -f your_branch

Texto de Doc :

Pode las entradas anteriores al tiempo especificado. Si no se especifica esta opción, el tiempo de vencimiento se toma del ajuste de configuración gc.reflogExpire, que a su vez tiene un valor predeterminado de 90 días. --expire = todas las entradas de ciruelas pasas independientemente de su edad; --expire = nunca desactiva la poda de entradas accesibles (pero vea --expire-unreachable).

Entonces puedes hacer:

1- git reflog

ingrese la descripción de la imagen aquí

2- elige Head_Number con el que desea recuperarse git reset –hard HEAD@{HEAD-NUMBER}

ingrese la descripción de la imagen aquí

3- puedes ver todas las confirmaciones en este encabezado por git cherry -v branch_name

4- al final debes forzar el empuje git push -f branch_name

O

1- obtenga el número de SHA de su cliente GIT (interfaz)

git reset --hard commit_SHA

2- empuje forzado

git push -f your_branch

Espero que esto ayude

Jacob
fuente
2

Hice lo mismo mientras deshacía un último empujón para un solo archivo. Terminé volviendo al estado original del repositorio. Estaba usando comandos git de Linus ya que tenía la copia local en Linux. Por suerte, esa copia seguía intacta.

Todo lo que hice fue (después de hacer frenéticamente algunas copias más del repositorio local):

git add .
git status

(decía que origin / master estaba por delante en 68 confirmaciones, bien ... esas fueron todas las confirmaciones que eliminé)

git remote set-url origin <GIT_SSH_URL>
git push

Y todo se restauró tal como estaba antes de que hiciera un fuerte empujón. Lo más importante que debe recordar es no realizar nunca un git checkout. después de haber empujado con fuerza. Pero la mejor práctica es deshabilitar la opción de inserción. Nunca lo volveré a usar. ¡Aprendí mi lección!

Pran
fuente
1

Para las personas en situaciones realmente malas como yo (por ejemplo, si recibe bad objecterrores al ejecutar git reset --hard):

Escribí un script llamado treesaver que extrae todos sus archivos de la API de GitHub como último recurso. Así es como se usa:

  1. Clona el treesaverguión y cdhazlo.
  2. Busque la SHAcadena del árbol que le gustaría restaurar accediendo https://api.github.com/repos/<your_username_or_org>/<repo>/events.
  3. En la payloadpropiedad correspondiente a su evento push, busque el commitque le gustaría volver y haga clic en su url.
  4. Debajo commit.tree, copie el tree's url.
  5. Corre python3 main.py <tree_url> <path_to_save_to>.

Por ejemplo, en mi caso, ejecutaría:

python3 main.py https://api.github.com/repos/anthonykrivonos/my-repo/git/trees/1234567 .

Por supuesto, los RP son bienvenidos.

Anthony Krivonos
fuente
0

Aquí puede leer las decisiones https://evilmartians.com/chronicles/git-push---force-and-how-to-deal-with-it

El segundo me ayudó. Hice mal estos comandos

1) (some-branch) git pull -> correct command was git pull origin some-branch

2) (some-branch) git push -f origin some-branch

Después de estos comandos perdí tres confirmaciones. Para recuperarlos miré a la terminal donde hice incorrectamente 'git pull' y vi una salida como

60223bf ... 0b258eb alguna-rama -> origen / alguna-rama

El segundo hash 0b258eb era exactamente lo que necesitaba. Entonces, tomé este hash y produje el comando

git push --force origin 0b258eb:some-branch
Andrey
fuente