web-dev-qa-db-fra.com

Refaire une fusion annulée dans Git

J'ai rencontré un petit problème ici: j'avais une branche spécifique au problème 28s dans Git, que j'ai fusionné dans la branche générale develop. Il s'avère que je l'avais fait trop vite, alors j'ai utilisé git-revert pour annuler la fusion. Maintenant, cependant, le temps est venu de fusionner 28s dans develop, mais la commande git-merge voit la fusion originale et annonce avec bonheur que tout va bien et que les branches ont déjà été fusionnées. Qu'est-ce que je fais maintenant? Créer un 'Revert "Revert" 28s -> develop ""' commit? Cela ne semble pas être un bon moyen de le faire, mais je ne peux en imaginer aucun pour le moment.

A quoi ressemble l'arborescence:

Git log output

199
Toms Mikoss

Vous devez "revenir en arrière". Cela dépend de la façon dont vous avez rétabli cela, ce ne sera peut-être pas aussi facile que ça en a l'air. Regardez le document officiel sur ce sujet .

---o---o---o---M---x---x---W---x---Y
              /
      ---A---B-------------------C---D

autoriser:

---o---o---o---M---x---x-------x-------*
              /                       /
      ---A---B-------------------C---D

Mais est-ce que tout fonctionne? Bien sûr que si. Vous pouvez annuler une fusion et, d’un point de vue purement technique, git l’a fait très naturellement et n’a eu aucun problème réel.
Il a juste considéré qu'il s'agissait d'un changement de "état avant fusion" à "état après fusion", et c'était tout.
Rien de compliqué, rien d’étrange, rien de très dangereux. Git le fera sans même y penser.

Donc, d’un point de vue technique, il n’ya rien de mal à annuler une fusion, mais sous un angle de workflow, c’est quelque chose que vous devriez généralement essayer d’éviter .

Si possible, par exemple, si vous rencontrez un problème qui a été fusionné dans l’arborescence principale plutôt que d’annuler la fusion, essayez vraiment difficile de :

  • divisez le problème en deux dans la branche que vous avez fusionnée et corrigez-le,
  • ou essayez d'inverser le commit individuel qui l'a causé.

Oui, c'est plus complexe, et non, ça ne va pas toujours marcher (parfois la réponse est: "oups, je n'aurais vraiment pas dû le fusionner, car il n'était pas encore prêt, et j'ai vraiment besoin d'annuler all de la fusion "). Dans ce cas, vous devriez vraiment annuler la fusion, mais lorsque vous souhaitez refaire la fusion, vous devez maintenant le faire en annulant la restauration.

149
J-16 SDiZ

Supposons que vous avez une telle histoire

---o---o---o---M---W---x-------x-------*
              /                      
      ---A---B

Où A, B échoue commet et W - revient à M

Donc, avant de commencer à résoudre les problèmes rencontrés, je fais un choix sélectif de W s’engager dans ma branche.

git cherry-pick -x W

Puis je rétablis W commit sur ma branche

git revert W 

Après je peux continuer à réparer.

L'histoire finale pourrait ressembler à:

---o---o---o---M---W---x-------x-------*
              /                       /     
      ---A---B---W---W`----------C---D

Lorsque j'envoie un PR, cela montre clairement que le PR est annulé, il ajoute de nouveaux commits.

47
Maksim Kotlyar

Pour revenir en arrière sans trop gâcher votre flux de travail:

  • Créer une copie de la corbeille locale de develop
  • Revert le revert commit sur la copie locale de develop
  • Fusionnez cette copie dans votre branche de fonctionnalités et transmettez-la à votre serveur git.

Votre branche de fonctionnalité devrait maintenant pouvoir être fusionnée normalement lorsque vous êtes prêt. Le seul inconvénient ici est que vous aurez quelques commits de fusion/annulation supplémentaires dans votre historique.

7
Sam Dufel

Pour revenir en arrière dans GIT:

git revert <commit-hash-of-previous-revert>
5
Richard

Au lieu d'utiliser git-revert, Vous auriez pu utiliser cette commande dans la branche devel pour jeter (annuler) le mauvais commit de fusion (au lieu de simplement l'annuler).

git checkout devel
git reset --hard COMMIT_BEFORE_WRONG_MERGE

Cela ajustera également le contenu du répertoire de travail en conséquence. Attention:

  • Enregistrez vos modifications dans la branche de développement (depuis la fusion incorrecte) car elles aussi seront effacées par le git-reset. Tous les commits après que celui que vous spécifiez comme argument git reset Auront disparu!
  • De même, ne le faites pas si vos modifications ont déjà été extraites d'autres référentiels, car la réinitialisation réécrira l'historique.

Je recommande d’étudier attentivement la page de manuel git-reset Avant d’essayer ceci.

Maintenant, après la réinitialisation, vous pouvez réappliquer vos modifications dans devel puis faire

git checkout devel
git merge 28s

Ce sera une véritable fusion de 28s Dans devel comme le premier (qui est maintenant effacé de l'historique de git).

3
knweiss

Je viens de trouver ce post lorsque je suis confronté au même problème. Je trouve ci-dessus plus effrayant de faire réinitialiser des disques, etc.

Au lieu de cela, j’ai vérifié le commit auquel je voulais que la branche revienne, par exemple. git checkout 123466t7632723. Puis converti en une branche git checkout my-new-branch. J'ai ensuite supprimé la branche que je ne voulais plus. Bien sûr, cela ne fonctionnera que si vous êtes capable de jeter la branche que vous avez foirée.

1
Claire

Je vous suggère de suivre les étapes ci-dessous pour rétablir un retour, dites SHA1.

git checkout develop #go to develop branch
git pull             #get the latest from remote/develop branch
git branch users/yourname/revertOfSHA1 #having HEAD referring to develop
git checkout users/yourname/revertOfSHA1 #checkout the newly created branch
git log --oneline --graph --decorate #find the SHA of the revert in the history, say SHA1
git revert SHA1
git Push --set-upstream Origin users/yourname/revertOfSHA1 #Push the changes to remote

Maintenant, créez PR pour la branche users/yourname/revertOfSHA1

1
Venkataraman R
  1. créer une nouvelle branche à commit avant la fusion d'origine - appelez-la 'develop-base'
  2. effectue une rebase interactive de 'develop' par-dessus de 'develop-base' (même si c'est déjà au top). Lors de la création d’une rebase interactive, vous aurez la possibilité de supprimer à la fois le commit de fusion et le commit qui a annulé la fusion, c’est-à-dire supprimer les deux événements de l’historique git.

À ce stade, vous disposez d'une branche "en développement" propre à laquelle vous pouvez fusionner votre fonction comme vous le faites régulièrement.

1
Misha Mostov