Comment supprimer définitivement quelques validations de la branche distante


490

Je sais que c'est la réécriture de l'histoire qui est mauvaise yada yada.

Mais comment supprimer définitivement quelques validations de la branche distante?


96
Oui, c'est vraiment mauvais yada yada, mais pour une raison quelconque, j'ai besoin de le préférer.
James Morris

44
Je sais que c'est stupide, mais parfois ça se passe - comme tester les connexions et utiliser des mots de passe en texte brut dans votre code, qui sont de véritables informations d'identification. Et oups ...
frhd

6
authentiques identifiants de connexion .. Ouais me rappelle quelques whoopos
Hello Universe

1
Duplication possible des validations de suppression à partir d'une succursale dans Git
wjandrea

2
Je suis tellement fatigué de ce discours académique sur la façon dont c'est dangereux et comment cela ne devrait jamais être fait yada yada. Il y a des moments où il est de loin préférable de supprimer des éléments de l'historique Git et de gérer les conflits / ruptures d'autres développeurs. C'est vraiment aussi simple que cela. Les gens qui ignorent cela n'ont probablement jamais travaillé en dehors d'une salle de classe.
écraser le

Réponses:


369

Vous git reset --hardvotre branche locale pour supprimer les modifications de l'arborescence de travail et de l'index, et vous git push --forcevotre branche locale révisée vers la télécommande. ( autre solution ici , consistant à supprimer la branche distante et à la repousser)

Cette réponse SO illustre le danger d'une telle commande, surtout si les gens dépendent de l'historique distant pour leurs propres dépôts locaux.
Vous devez être prêt à signaler aux gens la section RECOVERING FROM UPSTREAM REBASE de la git rebasepage de manuel


Avec Git 2.23 (août 2019, neuf ans plus tard), vous utiliseriez la nouvelle commande git switch.
Soit: (remplacer par le nombre de validations à supprimer)git switch -C mybranch origin/mybranch~n
n

Cela restaurera l'index et l'arborescence de travail, comme un git reset --hardferait.


Étrange. C'est comme si j'avais déjà essayé ça. Avec quelques rebasages - fonctionne comme un charme. Merci.
Arnis Lapsa

7
@Arnis: parfait alors;) push --forceloin
VonC

J'ai utilisé BFG Repo-Cleaner pour se débarrasser de certaines données sensibles, ce qui m'a laissé une branche "sans nom" avec le fichier d'origine dessus, après avoir réinitialisé le dernier commit voulu et avoir poussé dur à l'origine, tout s'est bien passé (:
Rodrirokr

Notez que l'URL du commit est toujours en vie (au moins pendant un certain temps) donc si quelqu'un a l'URL du commit (vous l'avez donné à Dieu sait pourquoi), il pourra accéder au code.
Mosh Feu

1
@MoshFeu True: git gcn'est pas toujours exécuté assez souvent du côté distant. Par exemple sur GitHub: twitter.com/githubhelp/status/387926738161774592?lang=es
VonC

248

Notez simplement d'utiliser le last_working_commit_id, lorsque vous annulez un commit qui ne fonctionne pas

git reset --hard <last_working_commit_id>

Nous ne devons donc pas réinitialiser ce commit_idque nous ne voulons pas.

Alors bien sûr, nous devons pousser vers la branche distante:

git push --force

10
Réponse parfaite, élégante et simple. Je viens de revenir au dernier commit Stabe dont j'avais besoin à la fois à distance et localement
lauWM

2
Cela m'a aussi fait perdre mes changements locaux. Je ne m'attendais pas à ça. Mais meh, mieux que de valider votre mot de passe personnel pour repo de travail.
Airwavezx

3
vous pouvez enregistrer vos modifications locales avec git stash .... faire certaines choses .... et git stash pop (vos modifications locales sont de retour)
MonTea

Cela me donne une erreur comme "à distance: erreur: refuser les références / têtes / maître à avance rapide (vous devez tirer en premier)"
Saurabhcdt

@Airwavezx c'est ce qui git reset --hardest censé faire.
Luke

146

Important: Assurez-vous de spécifier quelles branches sur "git push -f" ou vous pourriez modifier par inadvertance d'autres branches! [*]

Trois options sont présentées dans ce didacticiel . En cas de rupture du lien, je laisse ici les principales étapes.

  1. Annuler le commit complet
  2. Supprimer le dernier commit
  3. Supprimer le commit d'une liste

1 Annuler le commit complet

git revert dd61ab23

2 Supprimer le dernier commit

git push <<remote>> +dd61ab23^:<<BRANCH_NAME_HERE>>

ou, si la succursale est disponible localement

git reset HEAD^ --hard
git push <<remote>> -f

où + dd61 ... est votre hachage de validation et git interprète x ^ comme le parent de x, et + comme une poussée forcée non accélérée.

3 Supprimer le commit d'une liste

git rebase -i dd61ab23^

Cela ouvrira et l'éditeur montrera une liste de tous les commits. Supprimez celui dont vous souhaitez vous débarrasser. Terminer le rebasage et pousser la force de repo.

git rebase --continue
git push <remote_repo> <remote_branch> -f

5
Assurez-vous de spécifier quelles branches sur "git push <remote_repo> <remote_branch> -f" ou vous pourriez modifier par inadvertance d'autres branches!
Nigel Sheridan-Smith

Seules les étapes 1 et 2 ont fait le travail et répondu à la question d'origine. (Ne pas exécuter l'étape 3)
Saad Benbouzid

Ce sont des options pour différents scénarios, pas des étapes à suivre. Dans mon cas, le rebase interactif (Option 3) a fait ce que je cherchais.
Steve Blackwell

Je devais cependant faire l'étape 3. Pourquoi ne devriez-vous pas exécuter ce @Saad? Heureusement, mon <<remote>> était simplement `` l'origine '' par défaut et <remote_branch> le `` maître '' par défaut
Bart

30

Si vous souhaitez supprimer par exemple les derniers 3validations, exécutez la commande suivante pour supprimer les modifications du système de fichiers (arborescence de travail) et l'historique des validations (index) sur votre branche locale:

git reset --hard HEAD~3

Exécutez ensuite la commande suivante (sur votre ordinateur local) pour forcer la branche distante à réécrire son historique:

git push --force

Toutes nos félicitations! Terminé!

Quelques notes:

Vous pouvez récupérer l'ID de validation souhaité en exécutant

git log

Ensuite , vous pouvez remplacer HEAD~Navec <desired-commit-id>comme ceci:

git reset --hard <desired-commit-id>

Si vous souhaitez conserver les modifications sur le système de fichiers et simplement modifier l'index (historique des validations), utilisez --softflag like git reset --soft HEAD~3. Ensuite, vous avez la possibilité de vérifier vos dernières modifications et de les conserver ou de les supprimer en totalité ou en partie. Dans ce dernier cas, runnig git statusaffiche les fichiers modifiés depuis <desired-commit-id>. Si vous utilisez l' --hardoption, git statusvous dira que votre branche locale est exactement la même que celle distante. Si vous n'utilisez pas --hardni --soft, le mode par défaut est utilisé --mixed. Dans ce mode, git help resetdit:

Réinitialise l'index mais pas l'arborescence de travail (c'est-à-dire que les fichiers modifiés sont conservés mais pas marqués pour validation) et signale ce qui n'a pas été mis à jour.


10

C'est peut-être trop peu trop tard, mais ce qui m'a aidé, c'est l'option «nucléaire» au son cool. Fondamentalement, en utilisant la commandefilter-branch vous pouvez supprimer des fichiers ou modifier quelque chose sur un grand nombre de fichiers tout au long de votre historique Git.

C'est mieux expliqué ici .


9
Ce n'est pas trop tard. Pourrait devenir utile pour les vagabonds ayant des problèmes similaires :)
Arnis Lapsa

9

Simplification de la réponse de pctroll, également basée sur cet article de blog .

# look up the commit id in git log or on github, e.g. 42480f3, then do
git checkout master
git checkout your_branch
git revert 42480f3
# a text editor will open, close it with ctrl+x (editor dependent)
git push origin your_branch
# or replace origin with your remote

2
Fonctionne pour moi, merci. Et je veux supprimer définitivement un commit (par exemple, contient pwd) de l'historique de la branche distante, comment faire?
Sourit le

1
Fonctionne pour moi aussi, mais j'ai la même question que Smiles, je ne veux que personne ne voie mon commit / réver dans l'histoire .. comment supprimer cela?
Roberto Rodriguez

4

Parfois, le moyen le plus simple de résoudre ce problème est de créer une nouvelle branche à partir de l'endroit où vous savez que le code est bon. Ensuite, vous pouvez laisser l'historique des branches errant seul au cas où vous auriez besoin de sélectionner d'autres validations ultérieurement. Cela garantit également que vous n'avez perdu aucun historique de validation.

De votre succursale locale errante:

git log

copier le hachage de validation sur lequel vous vouliez que la branche se trouve et quitter le journal git

git checkout theHashYouJustCopied
git checkout -b your_new_awesome_branch

Vous avez maintenant une nouvelle branche comme vous le souhaitez.

Si vous avez également besoin de conserver un commit spécifique de la branche errante qui ne se trouve pas sur votre nouvelle branche, vous pouvez simplement sélectionner ce commit spécifique dont vous avez besoin:

git checkout the_errant_branch
git log

Copiez le hachage de validation du seul commit dont vous avez besoin pour tirer dans la bonne branche et quitter le journal git.

git checkout your_new_awesome_branch
git cherry-pick theHashYouJustCopied

Tapotez-vous dans le dos.


très facile et peu importe si vous avez une branche aux jambes mortes? créer une nouvelle branche et en finir avec elle!
Andrew Fox

Ceci est une excellente réponse. Je suis heureux d'avoir fait cela au lieu de commettre des cerises ou de manipuler la branche distante.
Magnilex

0
 git reset --soft commit_id
 git stash save "message"
 git reset --hard commit_id
 git stash apply stash stash@{0}
 git push --force
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.