web-dev-qa-db-fra.com

Comment puis-je restaurer plusieurs commits Git (déjà envoyés) vers un référentiel publié?

Nouveau pour Git, et déjà déconner.

Je me suis engagé et j'ai appliqué certaines modifications à une machine de développement distante .. Je dois récupérer une version plus ancienne, mais garder la "mauvaise progression" jusqu'à présent pour continuer à travailler sur une branche distincte;

Je pensais le faire comme ça:

  1. Créer une branche locale nommée: "chose testée"
  2. Rétablit le référentiel local dans l'état où il a fonctionné (des modifications significatives, espérons-le, aideront)};
  3. Push to remote

  4. termine les tests sur l'objet testé 

  5. Fusionner "chose testée" dans dev
  6. Push to remote

Entre les étapes 3 et 5, d’autres développeurs pourraient s’engager et pousser, et j’ai bien peur que cela aboutisse à une "tragédie de fusion" - Quoi qu’il en soit, est-ce que cela peut être une bonne façon de procéder?

METTRE À JOUR:

Le principal problème réside ici sur 2)

Ici, sur le sujet: "intégrer le travail dans une branche de sujet" http://learn.github.com/p/undoing.html

Ils proposent:

  1. test de branche $ git
  2. $ git reset --hard a6b4c974

Ce faisant, les autres développeurs pourraient toujours:

$ git commit (sur la branche dev)

et je peux commander pour tester et le régler jusqu'au moment de fusionner.

Malgré toutes vos options, cela semble être une bonne approche à suivre. Cependant, il n’est pas précisé si cela peut être fait après que nous ayons poussé?

Veuillez noter ce qui suit: Depuis que j'ai apporté ces modifications et que j'ai tout gâché, personne d'autre n'a encore travaillé sur le référentiel. Donc, si je retourne le répertoire de travail, personne ne le remarquera.

54
MEM

Le problème

Vous pouvez utiliser un certain nombre de flux de travail. Le principal est de ne pas briser l’histoire dans une branche publiée à moins d’avoir communiqué avec toutes les personnes susceptibles de consommer la branche et désireuses de procéder à une intervention chirurgicale sur leurs clones. Il vaut mieux ne pas le faire si vous pouvez l'éviter.

Solutions pour les branches publiées

Les étapes décrites ont du mérite. Si vous avez besoin que la branche dev soit stable tout de suite, faites-le ainsi. Vous disposez de plusieurs outils pour Déboguer avec Git qui vous aideront à trouver le bon point de branche, puis vous pourrez annuler tous les commits entre votre dernier commit stable et HEAD.

Revenir en arrière commet un à la fois, en ordre inverse, ou utilisez la plage <first_bad_commit>..<last_bad_commit>. Les hachages sont le moyen le plus simple de spécifier la plage de validation, mais il existe d'autres notations. Par exemple, si vous avez poussé 5 mauvais commits, vous pouvez les annuler avec:

# Revert a series using ancestor notation.
git revert --no-edit dev~5..dev

# Revert a series using commit hashes.
git revert --no-edit ffffffff..12345678

Cela appliquera successivement les correctifs inversés à votre répertoire de travail, en revenant en arrière vers votre commit bien connu. Avec l'indicateur --no-edit, les modifications apportées à votre répertoire de travail seront automatiquement validées après l'application de chaque correctif inversé.

Voir man 1 git-revert pour plus d'options, et man 7 gitrevisions pour différentes manières de spécifier les commits à annuler.

Vous pouvez également vous séparer de votre HEAD, corriger les problèmes tels qu'ils doivent être et les fusionner à nouveau. Votre build sera cassé entre-temps, mais cela peut avoir un sens dans certaines situations.

La zone de danger

Bien sûr, si vous êtes absolument sûr que personne n'a extrait du référentiel depuis vos mauvais envois, et si la télécommande est un référentiel bare, vous pouvez alors effectuer une analyse non rapide. faire suivre.

git reset --hard <last_good_commit>
git Push --force

Cela laissera le refoc intact sur votre système et l'hôte en amont, mais vos mauvais commits disparaîtront de l'historique directement accessible et ne se propageront pas lors de l'extraction. Vos anciennes modifications resteront en place jusqu'à la taille des référentiels, mais seuls les Git ninjas pourront voir ou récupérer les commits que vous avez effectués par erreur.

105
Todd A. Jacobs

Si vous avez déjà transféré des éléments sur un serveur distant (et que d'autres développeurs travaillent depuis la même branche distante), il est important de garder à l'esprit que vous ne souhaitez pas réécrire l'historique.

Ne pas utiliser git reset --hard

Vous devez annuler les modifications. Dans le cas contraire, toute extraction comportant des commits supprimés sera rajoutée dans le référentiel distant lors de la prochaine activation; et toute autre commande les tirera lors du prochain tirage par la suite.

Si vous n'avez pas transféré les modifications sur une télécommande, vous pouvez utiliser

git reset --hard <hash>

Si vous avez} poussé les changements, mais que vous êtes sûr que personne ne les a retirés, vous pouvez utiliser

git reset --hard
git Push -f

Si vous avez} _ avez poussé les modifications et que quelqu'un les a entrées dans leur commande, vous pouvez toujours le faire, mais l'autre membre de l'équipe/de la caisse devra collaborer:

(you) git reset --hard <hash>
(you) git Push -f

(them) git fetch
(them) git reset --hard Origin/branch

Mais en règle générale, cela tourne au désordre. Donc, en revenant:

Les commits à supprimer sont les derniers

C'est peut-être le cas le plus fréquent, vous avez fait quelque chose - vous les avez expulsés et ensuite vous vous êtes rendu compte qu'ils ne devraient pas exister.

Vous devez d’abord identifier le commit sur lequel vous voulez revenir, vous pouvez le faire avec:

git log

il suffit de rechercher le commit avant vos modifications et de noter le hash de commit. vous pouvez limiter le journal aux commits les plus récents à l'aide de l'indicateur -n: git log -n 5

Puis réinitialisez votre branche à l'état que vous souhaitez que vos autres développeurs voient:

git revert  <hash of first borked commit>..HEAD

La dernière étape consiste à créer votre propre branche locale en appliquant à nouveau vos modifications annulées:

git branch my-new-branch
git checkout my-new-branch
git revert <hash of each revert commit> .

Continuez à travailler dans my-new-branch jusqu'à ce que vous ayez terminé, puis fusionnez-le dans votre branche de développement principale.

Les commits à supprimer sont mêlés à d'autres commits

Si les commits que vous souhaitez annuler ne sont pas tous ensemble, il est probablement plus facile de les annuler individuellement. Utilisez à nouveau git log pour trouver les commits que vous souhaitez supprimer, puis:

git revert <hash>
git revert <another hash>
..

Ensuite, créez à nouveau votre branche pour continuer votre travail:

git branch my-new-branch
git checkout my-new-branch
git revert <hash of each revert commit> .

Encore une fois, piratez et fusionnez lorsque vous avez terminé.

Vous devriez vous retrouver avec un historique de commit qui ressemble à ceci sur my-new-branch

2012-05-28 10:11 AD7six             o [my-new-branch] Revert "Revert "another mistake""
2012-05-28 10:11 AD7six             o Revert "Revert "committing a mistake""
2012-05-28 10:09 AD7six             o [master] Revert "committing a mistake"
2012-05-28 10:09 AD7six             o Revert "another mistake"
2012-05-28 10:08 AD7six             o another mistake
2012-05-28 10:08 AD7six             o committing a mistake
2012-05-28 10:05 Bob                I XYZ nearly works

Better way®

Surtout que maintenant que vous connaissez les dangers de plusieurs développeurs travaillant dans la même branche, pensez à utiliser les branches de fonctionnalités toujours pour votre travail. Tout ce que cela signifie, c’est de travailler dans une branche jusqu’à ce que quelque chose soit terminé et de la fusionner ensuite avec votre branche principale. Pensez également à utiliser des outils tels que git-flow pour automatiser la création de branches de manière cohérente.

25
AD7six
git revert HEAD -m 1

Dans la ligne de code ci-dessus. "Le dernier argument représente"

  • 1 - annule un commet. 2 - annule les derniers commits. n - rétablit les derniers n commits

ou 

git reset --hard siriwjdd

0
Sireesh Yarlagadda