Comment récupérer d'un git push-force?

Voici ce qui s'est passé:

J'ai deux branches git distantes: master et feature1. Pour une raison quelconque, je dois utiliser git push --force pour la branche feature1, mais je ne savais pas quand j'utilise git push --force il poussera également la branche master. Ensuite, un désastre s'est produit, car j'ai poussé ma branche locale master vers le référentiel distant.

, Heureusement, ma branche locale n'est pas trop loin de la télécommande. Fondamentalement, Mon master distant a deux requêtes d'extraction fusionnées avant mon master local.

Donc mon problème est: puis-je rouvrir la demande d'extraction et remerger? J'ai remarqué qu'il existe une version de validation pour la demande de fusion, donc je suis inquiet si je fais simplement une nouvelle demande de traction, cela va gâcher quelque chose? Idéalement, je veux juste refaire la fusion des deux demandes.

Y a-t-il un autre moyen de se remettre de cette catastrophe? J'ai appris que le --force est un très, très mauvais choix. :(

Mise à jour, exemple de ce qui s'est passé:

J'ai les branches suivantes:

master
feature1
origin/master
origin/feature1

J'intègre deux pull requêtes en utilisant Auto merge pull requests de GitHub. Ensuite, je n'ai pas récupéré la branche master sur ma machine locale. Ainsi, je pense que mon origin/master est deux versions derrière le maître à distance.

Ensuite, j'ai accidentellement utilisé git -f push, qui a écrasé la branche distante et maintenant j'ai perdu les commits des requêtes d'extraction sur le référentiel distant.

Comment puis-je en récupérer sans gâcher l'historique des autres contributeurs?

26
demandé sur Jawa 2012-09-24 19:55:56

2 réponses

Vous pouvez toujours restaurer l'état précédemment observé de master, en réinitialisant l'ancien commit et en émettant un autre push -f. Les étapes impliquées ressemblent généralement à ceci:

# 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

Notez, cependant, que cela restaure master distant à l'état le plus récemment récupéré par git fetch ou équivalent. Tous les commits poussés par d'autres après la dernière fois que vous avez récupéré seront perdus. Cependant, ces commits seront toujours disponibles dans leur reflogs, afin qu'ils puissent les restaurer en utilisant des étapes comme la surtout.

70
répondu user4815162342 2017-03-07 11:58:24

Notez que, avec Github, vous pouvez utiliser L'API pour récupérer un push forcé même si vous n'avez pas le référentiel cloné localement (c'est-à-dire lorsque vous n'avez pas de reflog), ou le commit sha.

Tout d'abord, vous devez obtenir le commit SHA précédent, celui avant le push forcé:

curl -u <username> https://api.github.com/repos/:owner/:repo/events

Ensuite, vous pouvez créer une branche à partir de ce sha:

curl -u <github-username> -X POST -d '{"ref":"refs/heads/<new-branch-name>", "sha":"<sha-from-step-1>"}' https://api.github.com/repos/:owner/:repo/git/refs

Enfin, vous pouvez cloner le référentiel localement, et forcer push à nouveau à master:

git clone repo@github
git checkout master
git reset --hard origin/<new-branch-name>
git push -f origin master

Notez qu'avec deux facteurs l'authentification, vous devez fournir un jeton (voir ici pour plus d'informations).

Crédit: Sankara Rameswaran

10
répondu GHugo 2017-04-16 18:32:30