Annuler une `` poussée de git ''

592

Voici ce que j'ai fait sur ma branche supposée stable ...

% git rebase master
First, rewinding head to replay your work on top of it...
Fast-forwarded alpha-0.3.0 to master.
% git status
# On branch alpha-0.3.0
# Your branch is ahead of 'origin/alpha-0.3.0' by 53 commits.
#
nothing to commit (working directory clean)
% git push
Fetching remote heads...
  refs/
  refs/heads/
  refs/tags/
  refs/remotes/
'refs/heads/master': up-to-date
updating 'refs/heads/alpha-0.3.0'
  from cc4b63bebb6e6dd04407f8788938244b78c50285
  to   83c9191dea88d146400853af5eb7555f252001b0
    done
'refs/heads/unstable': up-to-date
Updating remote server info

C'était une erreur, comme je m'en suis rendu compte plus tard. Je voudrais annuler tout ce processus et rétablir la branche alpha-0.3.0 à ce qu'elle était.

Que devrais-je faire?

Cyrus
la source
ce post stackoverflow peut-être? stackoverflow.com/questions/134882/undoing-a-git-rebase
Steen
4
Ce n'est pas vraiment la même situation, l'annulation d'un rebase est un scénario de référentiel local, l'annulation d'un push git implique un référentiel distant et peut être plus délicat en fonction de l'accès dont vous disposez.
CB Bailey
Steen - vous avez raison - j'aurais probablement dû, je suppose. J'ai pensé que le dépôt béni dont tout le monde tirait est plus une tâche d'administration et appartient donc ici, où git côté client général est une question de stackoverflow.
Cyrus
Précision rapide - je suppose que si vous faites référence à un commit git par une valeur de hachage partielle , git supposera que vous parlez du commit dont le hachage commence par cette chaîne?
Gershom

Réponses:

944

Vous devez vous assurer qu'aucun autre utilisateur de ce référentiel ne récupère les modifications incorrectes ou n'essaie de construire au-dessus des validations que vous souhaitez supprimer car vous êtes sur le point de rembobiner l'historique.

Ensuite, vous devez «forcer» à pousser l'ancienne référence.

git push -f origin last_known_good_commit:branch_name

ou dans votre cas

git push -f origin cc4b63bebb6:alpha-0.3.0

Vous avez peut-être receive.denyNonFastForwardsdéfini le référentiel distant. Si tel est le cas, vous obtiendrez une erreur qui comprend la phrase [remote rejected].

Dans ce scénario, vous devrez supprimer et recréer la branche.

git push origin :alpha-0.3.0
git push origin cc4b63bebb6:refs/heads/alpha-0.3.0

Si cela ne fonctionne pas - peut-être parce que vous avez receive.denyDeletesdéfini, vous devez avoir un accès direct au référentiel. Dans le référentiel distant, vous devez alors faire quelque chose comme la commande de plomberie suivante.

git update-ref refs/heads/alpha-0.3.0 cc4b63bebb6 83c9191dea8
CB Bailey
la source
16
Une réponse parfaite et bien expliquée - merci beaucoup. Pour tous ceux qui tombent sur cela, pour des raisons académiques, j'ai essayé les deux premières approches, et les deux ont fonctionné - évidemment, si la première fonctionne, c'est l'approche la plus propre. Si je vous éveillais 10 fois Charles, je le ferais. :)
Cyrus
139
Pour référence rapide, la première ligne ici estgit push -f origin last_known_good_commit:branch_name
philfreo
5
git push -f origin cc4b63bebb6: alpha-0.3.0 => celui-ci m'a aidé, notez alpha-0.3.0 est le nom de la branche et cc4b63bebb6 est l'ID de validation auquel nous souhaitons revenir. ainsi, après avoir exécuté cette commande, nous serons dans l'ID de validation cc4b63bebb6.
kumar
22
Cette solution est très dangereuse si vous travaillez dans un référentiel partagé. En tant que meilleure pratique, tous les commits poussés vers un référentiel distant partagé devraient être considérés comme «immuables». Utilisez 'git revert' à la place: kernel.org/pub/software/scm/git/docs/…
Saboosh
1
jww - par rapport à tout le reste, git est l'outil de contrôle de source le plus riche en fonctionnalités et le plus efficace disponible. Chaque équipe l'utilise différemment. Cela vaut la peine de passer un week-end à jouer avec un nouveau référentiel et à parcourir tous les scénarios courants. Une fois que vous y avez consacré du temps, le développement est beaucoup moins stressant.
user1491819
165

Je pense que vous pouvez aussi faire ceci:

git checkout alpha-0.3.0
git reset --hard cc4b63bebb6
git push origin +alpha-0.3.0

Ceci est très similaire à la dernière méthode, sauf que vous n'avez pas à fouiner dans le référentiel distant.

Benny Wong
la source
9
Cela a également fonctionné pour moi, mais il convient de noter que cela "réécrira" l'historique sur la télécommande. C'est peut-être ce que vous voulez, mais ce n'est peut-être pas le cas!
Tom
3
+1 pour cette réponse qui m'a vraiment aidé. Je voulais également ajouter (et clarifier les choses) que l'ID de validation (qui vient après le --hardparamètre " ") devrait être l'ID de la validation à laquelle vous souhaitez réinitialiser votre branche.
Michael Dautermann
1
Réécrit bien l'histoire ... quiconque aurait pu tirer les changements, je me suis juste assuré qu'ils le faisaient git reset --hard [commit_id]pour ne pas déranger le continuum espace-temps.
Alien Life Form
9
À quoi sert le + dans "git push origin + alpha-0.3.0"?
jpierson
1
@jpierson +force la poussée à avoir lieu, de la même manière que -f(mais légèrement différente: stackoverflow.com/a/25937833/1757149 ). Sans elle, si vous essayez git push origin alpha-0.3.0la poussée échouera: Updates were rejected because the tip of your current branch is behind.
A__
106

git revert est moins dangereux que certaines des approches suggérées ici:

prompt> git revert 35f6af6f77f116ef922e3d75bc80a4a466f92650
[master 71738a9] Revert "Issue #482 - Fixed bug."
 4 files changed, 30 insertions(+), 42 deletions(-)
prompt> git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)
prompt>

Remplacez 35f6af6f77f116ef922e3d75bc80a4a466f92650 par votre propre commit.

neoneye
la source
2
Comment puis-je trouver l'ID 35f6af6f77f116ef922e3d75bc80a4a466f92650? Cette réponse serait meilleure si vous pouviez expliquer cela.
Volomike
2
@Volomike (et les développeurs Google du futur), cette question décrit de nombreuses façons de l'obtenir: contrôle de version et question de hachage sur SO
Jaime
C'est la bonne réponse, car avec "git reset" vous ne devriez pas être en mesure de pousser (les mises à jour ont été rejetées parce que la pointe de votre branche actuelle est derrière son homologue distant) ou vous devez forcer la traction qui n'est pas vraiment propre.
Thomas Decaux
Cela fonctionnait pour moi. Cependant, soyez prudent car revert annulera toutes les modifications dans vos fichiers locaux.
user1941537
J'ai opté pour cette approche plusieurs fois, mais j'utilise également git rebase -i <id-before-last-good-commit> pour effectuer un rebase interactif et nettoyer l'historique comme suggéré ici, stackoverflow.com/questions/5189560/… .
Ernesto Allely
35

La solution acceptée (de @charles bailey) est très dangereuse si vous travaillez dans un repo partagé.

En tant que meilleure pratique, tous les commits poussés vers un référentiel distant partagé devraient être considérés comme «immuables». Utilisez plutôt 'git revert': http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#fixing-mistakes

https://git-scm.com/book/be/v2/Git-Basics-Undoing-Things

Saboosh
la source
Quelles sont exactement les instructions que vous prescrivez? Vous semblez seulement avoir d'anciens liens.
2016
32

Une façon de le faire sans perdre les changements que vous vouliez:

git reset cc4b63b 
git stash
git push -f origin alpha-0.3.0
git stash pop

Ensuite, vous pouvez choisir les fichiers que vous vouliez pousser

curmil
la source
19

Une autre façon de procéder:

  1. créer une autre branche
  2. extraire le commit précédent sur cette branche en utilisant "git checkout"
  3. pousser la nouvelle branche.
  4. supprimer l'ancienne branche et pousser la suppression (utiliser git push origin --delete <branch_name>)
  5. renommer la nouvelle branche en ancienne branche
  6. pousser à nouveau.
Rushabh Mehta
la source
2
Celui-ci ressemble à une vraie solution lorsque vous avez déjà commis des erreurs de repo
Illarion Kovalchuk
17
git push origin +7f6d03:master

Cela ramènera votre repo au numéro de commit mentionné

ireshika piyumalie
la source
2
C'est la réponse la plus simple. Vous êtes un épargnant en direct.
Ekundayo Blessing Funminiyi
2
N'oubliez pas que cela ne réinitialisera pas vos fichiers locaux.
K-Gun
11

Annuler plusieurs validations git reset --hard 0ad5a7a6 (Fournissez simplement un hash SHA1 de validation)

Annuler le dernier commit

git reset --hard HEAD ~ 1 (les modifications apportées au dernier commit seront supprimées) git reset --soft HEAD ~ 1 (les modifications apportées au dernier commit seront disponibles sous forme de modifications locales non validées)

Jaymin
la source
9

Scénario 1 : Si vous souhaitez annuler le dernier commit, par exemple 8123b7e04b3, voici la commande (cela a fonctionné pour moi):

git push origin +8123b7e04b3^:<branch_name>

La sortie ressemble à ci-dessous:

Total 0 (delta 0), reused 0 (delta 0)
To https://testlocation/code.git
 + 8123b7e...92bc500 8123b7e04b3^ -> master (forced update)

Informations supplémentaires: Scénario 2 : Dans certaines situations, vous souhaiterez peut-être revenir en arrière sur ce que vous venez d'annuler (essentiellement annuler l'annulation) via la commande précédente, puis utilisez la commande ci-dessous:

git reset --hard 8123b7e04b3

Production:

HEAD is now at cc6206c Comment_that_was_entered_for_commit

Plus d'informations ici: https://github.com/blog/2019-how-to-undo-almost-anything-with-git

Barani r
la source
Le scénario 1 devrait être la réponse acceptée, car la question ne précisait pas quel engagement supprimer. La réponse acceptée ne supprime que le dernier commit. Cette réponse supprime tout commit.
Dominic Cerisano
0

Les réponses existantes sont bonnes et correctes, mais que se passe-t-il si vous devez annuler la pushmais:

  1. Vous souhaitez conserver les validations localement ou vous souhaitez conserver les modifications non validées
  2. Vous ne savez pas combien de commits vous venez de pousser

Utilisez cette commande pour rétablir la modification sur la référence:

git push -f origin refs/remotes/origin/<branch>@{1}:<branch>
Vlad274
la source
-2

Si vous voulez ignorer le dernier commit que vous venez de pousser dans la branche distante: cela ne supprimera pas le commit mais simplement l'ignorera en déplaçant le pointeur git vers le commit plus tôt, référencé par HEAD ^ ou HEAD ^ 1

git push origin +HEAD^:branch

Mais si vous avez déjà poussé ce commit et que d'autres ont tiré la branche. Dans ce cas, la réécriture de l'historique de votre branche n'est pas souhaitable et vous devriez plutôt annuler ce commit:

git revert <SHA-1>
git push origin branch
mkebri
la source
1
Oui! cela a fonctionné comme un charme lorsque vous travaillez avec github. Merci.
cukabeka
La question porte sur le "push" puis elle concerne la branche Remote. Non pour déplacer le HEAD sur un commit, ce qui signifie ignorer le dernier commit poussé, faites ceci: git push origin + HEAD ^: your_branch
mkebri