Annuler un push force

Git est un outil tellement puissant qu'on peut faire de grosses bêtises si on ne fait pas attention. Mais heureusement, Git est un outil tellement puissant qu'on peut réparer ses bêtises à condition de connaitre les bonnes commandes.

Alors aujourd'hui, j'ai push force une branche qui était mal configurée. Ma branche qu'on va appeler feature-cool avait pour upstream origin/master suite à une mauvaise manipulation. Mais j'avais pas fait attention… c'est vendredi matin ! Et donc, après avoir amendé un commit, j'ai machinalement fait un git push -f. Et c'est en regardant le log que je me suis aperçu, trop tard, de la bourde :

To git@github.com:user/project.git  
 + d72d68c...1f38597 feature-cool -> master (forced update)

Quel échec.

Un échec car ma branche feature-cool n'était pas forcément à jour de origin/master et aura probablement écrasé des commits fusionnés entre temps, mais aussi car ma branche feature-cool n'est pas passée par la phase de pull request et de review. Il fallait trouver un moyen de remettre les choses à leurs place !

git reflog

Nous allons alors utiliser git reflog ! reflog est une commande qui liste l'historique de toutes les commandes effectuées sur un dépôt. Sans paramètre, il affiche l'historique des commandes effectuées sur l'espace de travail local. Mais on peut lui demander d'afficher l'historique d'une banche distante :

git reflog show refs/remotes/origin/master  

S'afficheront alors les dernières opérations effectuées sur cette branche, dont la dernière devrait être notre bourde :

1f38597 refs/remotes/origin/master@{1}: update by push  
d72d68c refs/remotes/origin/master@{2}: pull --rebase: fast-forward  
…

"update by push" indique bien que l'opération fut un push forcé. C'est bien lui. Nous allons alors checkout le hash de la précédente opération :

git checkout d72d68c  

Nous voilà alors en mode "detached HEAD". Nous allons créer une nouvelle branche qu'on va appeler "master2" :

git checkout -b master2  

Et voilà, nous avons la branche master telle qu'elle était avant la bourde. Reste plus qu'à l'envoyer sur origin. Il suffit de modifier l'upstream puis de pousser de force :

git branch --set-upstream-to=origin/master  
git push -f  

Il vaut mieux évidemment faire tout ça immédiatement après s'être aperçu de la bourde, car si entre temps d'autres dev ont eu le temps de pousser sur master, la situation devient plus compliquée.

Hadrien

Hi, I'm a french Javascript Lead Developer, Web Architect from Toulouse, France. I've worked for 12 years for many projects with YUI, AngularJS, Aurelia.io and now React and React native.

Toulouse, France https://hadrien.eu