git push –force et comment y faire face
Vous êtes-vous déjà retrouvé dans une situation où une mauvaise commande git a fait des ravages sur le repo de votre projet ? Les gens font des erreurs, et parfois ces erreurs peuvent coûter des heures de temps à votre équipe. Dans ce tutoriel, nous allons vous montrer comment récupérer rapidement d’une git push --force
malheureuse.
Ne soyons pas trop confiants. Tôt ou tard, cela va se produire. En travaillant avec plusieurs remotes dans le même dépôt git, vous finirez par git push --force
dans master
(ou une autre branche importante avec laquelle il ne faut jamais jouer).
Cela peut arriver, par exemple, lors du déploiement avec Deis ou Heroku qui utilisent des remotes git distincts pour construire et déployer une application. Après une longue journée de travail, il est incroyablement facile d’exécuter git push --force
au lieu de l’habituel git push --force deis master
.
Oops ! En un clin d’œil, vos coéquipiers ont perdu tous leurs derniers travaux. Il est temps d’affronter leur rage.
Mais, comme nous le dit un excellent guide, NE PANIQUEZ PAS ! La bonne chose est que vous utilisez git, et cela signifie que tout peut être réparé.
Dans le meilleur des cas : quelqu’un d’autre qui travaille sur le même code a tiré une version récente du
master
juste avant que vous ne le cassiez. Alors tout ce que vous avez à faire est d’aller dans le chat de votre équipe et de demander à cette personne de pousser de force ses changements récents.
Si vous avez de la chance, leur dépôt local aura l’historique complet des commits, votre erreur sera écrasée par du code frais, et rien ne sera perdu. Mais que faire si vous n’avez pas cette chance ? Alors, lisez la suite !
Cas 1 : Vous étiez la dernière personne à pousser vers master avant l’erreur
Bonne nouvelle ! Vous avez tout ce dont vous avez besoin pour défaire votre erreur sous vos yeux. Il suffit de ne pas fermer ou effacer votre terminal. Tout d’abord, allez dans le chat de votre équipe et confessez vos péchés. Demandez aux gens de ne pas s’occuper du repo pendant la prochaine minute pendant que vous réparez les choses.
Dans la sortie de la commande git push --force
de votre shell, cherchez une ligne qui ressemble à celle-ci :
+ deadbeef...f00f00ba master -> master (forced update)
Le premier groupe de symboles (qui ressemble au préfixe SHA d’un commit) est la clé du sauvetage. deadbeef
est votre dernier bon commit vers la master
juste avant que vous n’infligiez des dégâts.
Donc tout ce dont vous avez besoin est de… pousser de force (combattre le feu par le feu !) ce commit vers la branche master
, par-dessus un mauvais.
$ git push --force origin deadbeef:master
Congratulations ! Vous avez sauvé la journée. Maintenant il est temps d’apprendre de vos erreurs.
Cas 2 : master a été modifié par quelqu’un d’autre avant que vous ne fassiez des bêtises
Donc, juste avant que vous ne fassiez git push --force
quelqu’un avait fermé un tas de pull requests, et le master
ne ressemble maintenant en rien à votre copie locale. Vous ne pouvez plus faire git push --force sha1:master
car vous n’avez pas de commits récents localement (et vous ne pouvez pas les obtenir avec git fetch
car ils n’appartiennent plus à aucune branche). Gardez tout de même votre calme et demandez à vos coéquipiers de ne pas utiliser la télécommande pendant un certain temps.
Nous allons bénéficier du fait que GitHub ne supprime pas immédiatement les commits inaccessibles. Bien sûr, vous ne pouvez pas non plus les récupérer, mais il existe une solution de contournement.
Notez que cela ne fonctionnera que si vous « surveillez » le dépôt, de sorte que tout ce qui s’y passe apparaît dans un flux affiché sur la page d’accueil de votre GitHub. Ouvrez ce flux et cherchez quelque chose comme ceci:
an hour agoUsername pushed to master at org/repo - deadbeef Implement foo - deadf00d Fix bar
Maintenant vous pouvez :
- Composer une URL
https://github.com/org/repo/tree/deadbeef
, oùdeadbeef
est un hachage du dernier bon commit de la branche endommagée; - Ouvrir le commutateur branches/balises dans l’interface web de GitHub ;
- Créer un nom pour une nouvelle branche temporaire (par ex.g.,
master-before-force-push
); - Cliquez sur « Créer une branche ».
Maintenant vous pouvez récupérer tous les commits manquants:
$ git fetchFrom github.com:org/repo * master-before-force-push -> origin/master-before-force-push
Votre problème est maintenant réduit à celui décrit dans un exemple précédent :
$ git push --force origin origin/master-before-force-push:master
Si vous avez toujours besoin que votre travail soit dans le master
, il suffit de rebaser par dessus :
$ git rebase origin/master
Comment éviter un tel désastre à l’avenir
-
GitHub et GitLab ont une fonctionnalité appelée » branches protégées « . » Marquez
master
,develop
,stable
, ou toute autre branche cruciale comme protégée et personne ne sera autorisé à forcer le push dans ces branches. Il est toujours possible de « déprotéger » temporairement une branche si vous avez vraiment besoin d’écraser l’historique.Lisez les docs GitHub pour plus de détails.
-
Au lieu de l’option
--force
, utilisez--force-with-lease
. Elle arrêtera l’opération de push si quelqu’un a poussé sur la même branche pendant que vous travailliez dessus (et n’a pas tiré de modifications).Voir cet article d’Atlassian.
-
Créez des alias pour les commandes qui utilisent
git push --force
afin d’éviter les actions destructives par accident :# ~/.gitconfig deploy = "!git push --force deis \"$(git rev-parse --abbrev-ref HEAD):master\""
Lisez le chapitre de ProGit sur les alias.
-
Ne faites jamais vos expériences dans la branche principale d’un dépôt !
git checkout -b experiments
est votre meilleur ami.
Conseil de pro : git push
a de nombreuses options. --force
et --all
fonctionnent particulièrement bien ensemble. Vous pouvez utiliser ce combo lorsque vous revenez au projet après plusieurs mois d’inactivité. Essayez-le si vous vous sentez très aventureux !
Leave a Reply