web-dev-qa-db-fra.com

Annuler les modifications apportées par la fusion

Le développeur était en train de valider de petites modifications sur deux fichiers. Mais pendant ce commit, il a eu un conflit de fusion qui a supprimé beaucoup de choses (probablement pas la dernière version mise à jour). Ensuite, cela a été poussé vers le dépôt partagé et certains autres développeurs ont fait d'autres commits.

Maintenant, nous avons remarqué que la fusion supprimait les fichiers importants et nous souhaitons le restaurer.
Comment puis-je faire cela sans perdre les modifications des prochains commits?

J'essayais de git revert commitsha, mais cela ne rapportait pas les modifications. Dois-je rétablir la mergesha? Comment puis-je le déterminer?

21
Sfisioza

git revert --mainline

Habituellement:

git revert --mainline 1 dd8cbe3e4

Où: 

  • dd8cbe3e4 est le commit de fusion incorrect que vous voulez annuler, et 
  • --mainline vous indique lequel des multiples validations précédentes doit être restauré (rappelez-vous qu'une validation de fusion comporte plusieurs commits parents et que vous ne pouvez en conserver qu'un) .
    • Je ne trouve pas de bonne explication sur la signification de 1, mais je suppose que 1,2,3... correspond à une liste de mappages sur les validations précédant immédiatement dd8cbe3e4, triées par ordre chronologique croissant vous voulez revenir à).

La source:

http://thezencoder.com/2013/09/05/how-to-correctly-revert-a-bad-merge-in-git/

24
Sridhar-Sarnobat

En bref, WARNING: il n'y a pas de véritable sûr moyen d'annuler une fusion sauf en en fait reset la branche vers la validation avant la fusion.

Laissez-moi vous expliquer et rechercher une référence existante pour le moment.

Citation de la réponse liée de Comment annuler un commit de fusion de git défectueux

En principe, annuler une fusion annulera les modifications de données, mais pas l'historique (graphique) changera. Par conséquent, il est prévu que l'annulation de votre fusion défectueuse ne fera rien.

Bien sûr, la réinitialisation de la branche serait l'approche la plus simple, mais elle présente des inconvénients si le résultat de la fusion a déjà été poussé vers un référentiel partagé (car vous réécrivez effectivement l'historique publié).

Voici la ventilation

  • git merge <someref> à fusionner (éventuellement valider après résolution des conflits)
  • Si vous découvrez tout de suite que vous souhaitez réinitialiser la branche avant la fusion:

    git reset HEAD@{1} 
         # optionally pass --hard to reset the working tree too
    
  • si vous ne le découvriez que plus tard, 

    • utilisez à chaque utilisation le reflog pour trouver le point avant la fusion. (HEAD@{1} est l'abréviation de la valeur précédente de la référence de tête actuelle, mais le reflog suit un historique limité de valeurs pour la référence de tête)

      git reflog
      
    • réinitialiser la branche

      git reset HEAD@{n} # substitute reflog entry index
      
    • éventuellement rebase/cherry-pick les commits effectués après la fusion

      git cherry-pick HEAD@{1} # just an example. interactive tools will make this easier
      
9
sehe

Une autre approche (plus sûre) consiste à créer un diff entre la dernière version du fichier et la version actuelle du fichier, puis à restaurer les pièces perdues par copier-coller.

Cela fonctionne toujours, n'a besoin d'aucune option de ligne de commande étrange, et n'altère pas les choses que vous devriez laisser tranquilles :-)

Eclipse, par exemple, dispose de bons outils pour sélectionner chaque différence et la copier dans l'une ou l'autre version. Utilisez simplement le menu "Comparer" pour ouvrir les deux versions côte à côte.

5
Aaron Digulla

En bref, vous pouvez faire un git reset --soft <commit> Où commit peut être HEAD^ (précédent), HEAD~2 (courant-2), un SHA, etc.

Avec --soft, toutes les modifications seront prêtes à être validées, ce qui vous permettra de modifier le commit. Avec --hard, les changements seront tous perdus.

Après avoir modifié la validation, vous devez forcer la transmission des modifications au référentiel partagé avec git Push --force.

Notez que vous devrez indiquer aux autres développeurs qu'ils doivent redistribuer leurs dépôts sur le référentiel partagé. (utilisez git pull --rebase). Cependant, ils pourraient avoir des conflits de fusion ... Gardez cela à l’esprit.

0
Hiery Nomus