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?
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.
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