Il s'agit d'un exemple où la conception de gitne correspond pas au git-flowflux de travail -ish que tout le monde utilise. Si vous avez developvérifié, bien sûr, vous souhaitez revenir à la branche de fonctionnalité 2-commit qui a introduit un bogue et non à la branche de développement partagée de plusieurs années. Se sent ridicule d'avoir besoin de le choisir -m 1.
pkamb
2
Juste une autre suggestion qui ne m'est jamais venue à l'esprit auparavant - si l'une des listes de validations des branches est petite, vous pourriez vous sentir plus à l'aise de revenir sur des validations individuelles au lieu d'une branche entière de validations.
Sridhar Sarnobat
Réponses:
1155
L' -moption spécifie le numéro parent . En effet, une validation de fusion a plusieurs parents et Git ne sait pas automatiquement quel parent était la ligne principale et quel parent était la branche que vous souhaitez annuler la fusion.
Lorsque vous affichez une validation de fusion dans la sortie de git log, vous verrez ses parents répertoriés sur la ligne qui commence par Merge:
commit 8f937c683929b08379097828c8a04350b9b8e183
Merge: 8989ee0 7c6b236
Author: Ben James <[email protected]>
Date: Wed Aug 17 22:49:41 2011 +0100
Merge branch 'gh-pages'
Conflicts:
README
Dans cette situation, git revert 8f937c6 -m 1vous obtiendrez l'arbre tel qu'il était 8989ee0et vous git revert -m 2le rétablirez tel qu'il était 7c6b236.
Pour mieux comprendre les ID parents, vous pouvez exécuter:
à partir de deux numéros 8989ee0, 7c6b236lequel choisir. Comment pourrais-je comprendre?
Arup Rakshit
12
Après le retour, je ne pense pas que l'on sera en mesure de corriger facilement le code dans la branche source et de fusionner à nouveau? kernel.org/pub/software/scm/git/docs/howto/…
IsmailS
10
En cherchant sur Google une meilleure explication, j'ai trouvé cet article qui, à mon avis, a fait un excellent travail pour passer en revue les détails. J'ai découvert après avoir lu que ce que je cherchais vraiment était la commande RESET, suivie d'une poussée forcée. Peut-être que cela aidera quelqu'un d'autre. atlassian.com/git/tutorials/…
Funktr0n
46
@ArupRakshit si vous exécutez git log 8989ee0et git log 7c6b236, vous devez connaître la réponse.
BMW
4
git log - fusionne pour voir toutes les fusions et git log --no-merges pour voir l'historique sans fusions. La fusion d'une branche ramène l'historique des branches fusionnées dans la cible et rend difficile la différenciation à l'aide d'un journal
Git
370
Voici un exemple complet dans l'espoir que cela aide quelqu'un:
Où se <commit-hash>trouve le hachage de validation de la fusion que vous souhaitez annuler et, comme indiqué dans l'explication de cette réponse , -m 1indique que vous souhaitez revenir à l'arborescence du premier parent avant la fusion.
La git revert ...ligne valide essentiellement vos modifications tandis que la deuxième ligne rend vos modifications publiques en les poussant vers la branche distante.
Je pensais que la git revertcommande avait déjà validé l'objet commit créé. Pour que cela ne se produise pas, vous devez saisir le --no-commitdrapeau
Delfic
2
Comme @Delfic l'a mentionné, le commit est déjà géré par la première ligne (j'avais besoin d'un: wq pour le valider) donc la deuxième ligne n'est pas nécessaire.
eka808
1
Ceci est déroutant. il n'y a que 2 lignes et aucun git commit .. quelqu'un peut-il éditer.
Jay Random
176
Ben vous a expliqué comment annuler un commit de fusion, mais il est très important que vous vous rendiez compte qu'en procédant ainsi
"... déclare que vous ne voudrez jamais que les modifications de l'arborescence soient apportées par la fusion. Par conséquent, les fusions ultérieures n'apporteront que les modifications de l'arborescence introduites par des validations qui ne sont pas les ancêtres de la fusion précédemment annulée. Cela peut ou non être ce que vous voulez. " (page de manuel git-merge) .
Un article / liste de diffusion lié à partir de la page de manuel détaille les mécanismes et les considérations impliqués. Assurez-vous simplement de comprendre que si vous annulez la validation de fusion, vous ne pouvez pas fusionner à nouveau la branche plus tard et vous attendre à ce que les mêmes modifications reviennent.
Mais vous pouvez annuler le retour pour les récupérer si nécessaire.
dalore
5
Merci. Il est très utile de savoir que le cas d'utilisation pour annuler une fusion - en raison d'un bogue, par exemple - puis fusionner à nouveau la branche entière une fois le bogue corrigé, est un cas courant.
Composante 10
3
Si vous êtes comme moi et que vous vouliez plus tard la fusion, vous pouvez soit annuler le retour, soit choisir le changement que vous avez annulé.
UnitasBrooks
Dans ma situation, j'ai frappé le devoir de «revenir en arrière» pour obtenir mon problème de modifications. La cueillette des cerises pourrait être une façon plus soignée? Je vais essayer ça la prochaine fois ...
Steven Anderson
79
Vous pouvez suivre ces étapes pour rétablir les validations incorrectes ou pour réinitialiser votre branche distante à l'état HEAD / état correct.
extraire la succursale distante du dépôt local. git checkout development
copier le hachage de validation (c'est-à-dire l'identifiant de la validation immédiatement avant la mauvaise validation) depuis le journal git
git log -n5
production:
commit 7cd42475d6f95f5896b6f02e902efab0b70e8038 "Fusionner la branche 'false-commit' dans 'development'"
commit f9a734f8f44b0b37ccea769b9a2fd774c0f0c012 "c'est un mauvais commit"
commit 3779ab50e72908da92 "
réinitialiser la branche sur le hachage de validation copié à l'étape précédente git reset <commit-hash> (i.e. 3779ab50e72908da92d2cfcd72256d7a09f446ba)
exécutez le git statuspour afficher toutes les modifications qui faisaient partie du mauvais commit.
exécutez simplement git reset --hardpour annuler tous ces changements.
forcez-vous à pousser votre branche locale à distance et notez que votre historique de commit est propre comme il était avant qu'il ne soit pollué. git push -f origin development
que se passe-t-il si entre-temps 20 développeurs ont tiré la dernière fusion de dev?
Ewoks
2
Je ne forcerais pas à pousser une branche de développement lorsqu'il y a 20 développeurs dans l'équipe utilisant cette branche. :) Dans ce cas, il est sage de simplement faire un commit de retour.
ssasi
4
C'est une très bonne solution lorsque vous travaillez seul ou si vous êtes certain qu'aucun autre développeur n'a tiré les engagements que vous avez ratés
Astuce: si vous faites cela dans votre entreprise, vous pourriez ne pas avoir l'autorisation.
eneski
3
ne jamais faire un push -frepo partagé
Baptiste Mille-Mathias
17
Parfois, le moyen le plus efficace de revenir en arrière consiste à prendre du recul et à remplacer.
git log
Utilisez le 2e hachage de validation (hachage complet, celui auquel vous souhaitez revenir avant l'erreur répertoriée), puis rebranchez-le à partir de là.
git checkout -b newbranch <HASH>
Supprimez ensuite l'ancienne branche, copiez la nouvelle branche à sa place et redémarrez à partir de là.
Si elle a été diffusée, supprimez l'ancienne branche de tous les référentiels, poussez la branche refaite vers la plus centrale et ramenez-la vers le bas pour toutes.
L'avertissement concernant la diffusion devrait vraiment être plus explicite sur la façon dont cette idée est horrible. Cela corrompra la version de cette branche pour tout le monde et n'est vraiment utile que si vous travaillez avec un référentiel distant (github / bitbucket) auquel vous seul avez accès.
RobbyD
Pas aussi mauvais que de pousser les fichiers de configuration modifiés en aval vers la production. Il ne sera pas corrompu, c'est juste un re-branchement d'un commit précédent, donc c'est un moyen détourné de déplacer le pointeur des branches vers une version antérieure. Espérons que cela
n'impacte
5
Si vous souhaitez annuler un mergecommit, voici ce que vous devez faire.
Tout d'abord, vérifiez le git logpour trouver l'ID de votre commit de fusion. Vous trouverez également plusieurs identifiants parents associés à la fusion (voir l'image ci-dessous).
Notez l'ID de validation de fusion affiché en jaune. Les ID parents sont ceux écrits sur la ligne suivante sous la formeMerge: parent1 parent2 . Maintenant...
Histoire courte:
Basculez vers la branche sur laquelle la fusion a été effectuée. Ensuite, faites simplement ce git revert <merge commit id> -m 1qui ouvrira une viconsole pour entrer le message de validation. Écrivez, enregistrez, quittez, c'est fait!
Longue histoire:
Basculez vers la branche sur laquelle la fusion a été effectuée. Dans mon cas, c'est la testbranche et j'essaie d'en supprimer la feature/analytics-v3branche.
git revertest la commande qui annule tout commit. Mais il y a une mauvaise astuce lors de l'annulation d'un mergecommit. Vous devez entrer le -mdrapeau sinon il échouera. À partir de là, vous devez décider si vous souhaitez rétablir votre branche et la faire ressembler exactement à ce qu'elle était sur parent1ou parent2via:
git revert <merge commit id> -m 1(revient à parent2)
git revert <merge commit id> -m 2(revient à parent1)
Vous pouvez enregistrer ces parents pour savoir dans quelle direction vous voulez aller et c'est la racine de toute la confusion.
Toutes les réponses couvraient déjà la plupart des choses, mais j'ajouterai mes 5 cents. En bref, annuler un commit de fusion est assez simple:
git revert -m 1 <commit-hash>
Si vous en avez la permission, vous pouvez le pousser directement vers la branche "master", sinon il vous suffit de le pousser vers votre branche "revert" et de créer une requête pull.
J'ai trouvé que la création d'un patch inverse entre deux points d'extrémité connus et l'application de ce patch fonctionneraient. Cela suppose que vous avez créé des instantanés (balises) à partir de votre branche principale ou même une sauvegarde de votre branche principale, par exemple master_bk_01012017.
Supposons que la branche de code que vous avez fusionnée dans master soit mycodebranch.
Maître de caisse.
Créez un patch inverse binaire complet entre le maître et votre sauvegarde.
git diff --binary master..master_bk_01012017 > ~/myrevert.patch
Appliquer le patch avec la signature
git am --signoff < myrevert.patch
Si vous devez introduire à nouveau ce code une fois qu'il est résolu, vous devrez dériver le maître rétabli et extraire la branche de correction
git branch mycodebranch_fixgit checkout mycodebranch_fix
Ici, vous devez trouver la clé SHA pour le retour et revenir au retour
git revert [SHA]
Maintenant, vous pouvez utiliser votre mycodebranch_fix pour résoudre les problèmes, valider et re-fusionner dans master une fois terminé.
La réponse correctement marquée a fonctionné pour moi mais j'ai dû passer un peu de temps à déterminer ce qui se passait .. J'ai donc décidé d'ajouter une réponse avec des étapes simples pour des cas comme le mien ..
Disons que nous avons obtenu les branches A et B .. Vous avez fusionné la branche A dans la branche B et poussé la branche B vers elle-même alors maintenant la fusion en fait partie .. Mais vous voulez revenir au dernier commit avant la fusion .. Que faire tu fais?
Accédez à votre dossier racine git (généralement le dossier du projet) et utilisez git log
Vous verrez l'historique des validations récentes - les validations ont des propriétés commit / author / date tandis que les fusions ont également une propriété merge - donc vous les voyez comme ceci:
Utilisez git log <parentHashA>et git log <parentHashB>- vous verrez les historiques de validation de ces branches parentes - les premiers validations de la liste sont les plus récentes
Prenez le <commitHash>commit que vous voulez, allez dans votre dossier racine git et utilisez git checkout -b <newBranchName> <commitHash>- cela créera une nouvelle branche à partir du dernier commit que vous avez choisi avant la fusion .. Voila, prêt!
J'ai également rencontré ce problème sur un PR qui a été fusionné avec la branche principale d'un dépôt GitHub.
Depuis que je voulais juste modifier quelques fichiers modifiés , mais pas tout change PR apporté, je devais amendle merge commitavec git commit --am.
Pas:
Accédez à la branche dont vous souhaitez modifier / rétablir certains fichiers modifiés
Faites les changements que vous souhaitez en fonction des fichiers modifiés
courir git add *ougit add <file>
exécuter git commit --amet valider
courir git push -f
Pourquoi c'est intéressant:
Il garde le commit de l'auteur du PR inchangé
Il ne casse pas l'arbre git
Vous serez marqué comme committer (fusionner l'auteur du commit restera inchangé)
Git agit comme si vous aviez résolu des conflits, il supprimera / changera le code dans les fichiers modifiés comme si vous demandiez manuellement à GitHub de ne pas le fusionner tel quel
J'ai trouvé une bonne explication pour annuler la fusion à partir de ce lien et j'ai copié collé l'explication ci-dessous et il serait utile au cas où le lien ci-dessous ne fonctionne pas.
Comment annuler une fusion défectueuse Alan ([email protected]) a déclaré:
J'ai une branche principale. Nous avons une branche sur laquelle certains développeurs travaillent. Ils prétendent qu'il est prêt. Nous le fusionnons dans la branche principale. Il casse quelque chose donc nous revenons à la fusion. Ils apportent des modifications au code. ils parviennent à un point où ils disent que c'est ok et nous fusionnons à nouveau. Une fois examinés, nous constatons que les modifications de code effectuées avant le retour ne sont pas dans la branche principale, mais les modifications de code après sont dans la branche principale. et a demandé de l'aide pour se remettre de cette situation.
L'histoire immédiatement après le "retour de la fusion" ressemblerait à ceci:
---o---o---o---M---x---x---W
/
---A---B
où A et B sont sur le développement latéral qui n'était pas si bon, M est la fusion qui apporte ces changements prématurés dans la ligne principale, x sont des changements sans rapport avec ce que la branche latérale a fait et déjà effectués sur la ligne principale, et W est le " annuler la fusion M "(W ne regarde-t-il pas M à l'envers?). IOW, "diff W ^ .. W" est similaire à "diff -RM ^ .. M".
Un tel "retour" d'une fusion peut être effectué avec:
$ git revert -m 1 M Une
fois que les développeurs de la branche latérale ont corrigé leurs erreurs, l'historique peut ressembler à ceci:
où C et D doivent réparer ce qui a été cassé en A et B, et vous pouvez déjà avoir d'autres changements sur la ligne principale après W.
Si vous fusionnez la branche latérale mise à jour (avec D à son extrémité), aucune des modifications apportées dans A ou B ne sera dans le résultat, car elles ont été annulées par W. C'est ce qu'Alan a vu.
Linus explique la situation:
La restauration d'un commit régulier annule simplement ce que ce commit a fait et est assez simple. Mais l'annulation d'un commit de fusion annule également les données modifiées par le commit, mais cela n'a absolument rien à voir avec les effets sur l' historique de la fusion. Ainsi, la fusion existera toujours, et elle sera toujours considérée comme joignant les deux branches, et les futures fusions verront cette fusion comme le dernier état partagé - et le retour qui a annulé la fusion apportée n'affectera pas du tout cela. Donc, un "retour" annule les modifications de données, mais ce n'est pas du tout un "défaire" dans le sens où il n'annule pas les effets d'un commit sur l'historique du référentiel. Donc, si vous pensez à "revenir" comme "annuler", alors vous allez toujours manquer cette partie des retours. Oui, cela annule les données, mais non, il n'annule pas l'historique. Dans une telle situation, vous voudrez d'abord revenir à la précédente, ce qui donnerait à l'histoire l'aspect suivant:
où Y est le retour de W. Un tel "retour du retour" peut se faire avec:
$ git revert W
Cet historique (en ignorant les conflits possibles entre ce que W et W..Y ont changé) équivaudrait à ne pas avoir du tout W ou Y dans l'historique:
Bien sûr, les modifications apportées en C et D peuvent toujours entrer en conflit avec ce qui a été fait par l'un des x, mais ce n'est qu'un conflit de fusion normal.
Comme Ryan l'a mentionné, cela git revertpourrait rendre la fusion difficile sur la route, donc ce git revertn'est peut-être pas ce que vous voulez. J'ai trouvé que l'utilisation de la git reset --hard <commit-hash-prior-to-merge>commande était plus utile ici.
Une fois que vous avez terminé la partie de réinitialisation matérielle, vous pouvez alors forcer le push vers la branche distante, c'est git push -f <remote-name> <remote-branch-name>-à- dire où <remote-name>est souvent nommé origin. À partir de là, vous pouvez refusionner si vous le souhaitez.
Tout ce qui implique des poussées de force est une mauvaise idée, sauf si vous êtes le seul à utiliser le référentiel et que vous savez exactement ce que vous faites. Revenir en arrière avec git revert, puis éventuellement revenir en arrière avec git revert (si vous avez besoin de revenir en arrière) est une alternative beaucoup plus sûre.
git
ne correspond pas augit-flow
flux de travail -ish que tout le monde utilise. Si vous avezdevelop
vérifié, bien sûr, vous souhaitez revenir à la branche de fonctionnalité 2-commit qui a introduit un bogue et non à la branche de développement partagée de plusieurs années. Se sent ridicule d'avoir besoin de le choisir-m 1
.Réponses:
L'
-m
option spécifie le numéro parent . En effet, une validation de fusion a plusieurs parents et Git ne sait pas automatiquement quel parent était la ligne principale et quel parent était la branche que vous souhaitez annuler la fusion.Lorsque vous affichez une validation de fusion dans la sortie de
git log
, vous verrez ses parents répertoriés sur la ligne qui commence parMerge
:Dans cette situation,
git revert 8f937c6 -m 1
vous obtiendrez l'arbre tel qu'il était8989ee0
et vousgit revert -m 2
le rétablirez tel qu'il était7c6b236
.Pour mieux comprendre les ID parents, vous pouvez exécuter:
et
la source
8989ee0
,7c6b236
lequel choisir. Comment pourrais-je comprendre?git log 8989ee0
etgit log 7c6b236
, vous devez connaître la réponse.Voici un exemple complet dans l'espoir que cela aide quelqu'un:
Où se
<commit-hash>
trouve le hachage de validation de la fusion que vous souhaitez annuler et, comme indiqué dans l'explication de cette réponse ,-m 1
indique que vous souhaitez revenir à l'arborescence du premier parent avant la fusion.La
git revert ...
ligne valide essentiellement vos modifications tandis que la deuxième ligne rend vos modifications publiques en les poussant vers la branche distante.la source
git revert
commande avait déjà validé l'objet commit créé. Pour que cela ne se produise pas, vous devez saisir le--no-commit
drapeauBen vous a expliqué comment annuler un commit de fusion, mais il est très important que vous vous rendiez compte qu'en procédant ainsi
Un article / liste de diffusion lié à partir de la page de manuel détaille les mécanismes et les considérations impliqués. Assurez-vous simplement de comprendre que si vous annulez la validation de fusion, vous ne pouvez pas fusionner à nouveau la branche plus tard et vous attendre à ce que les mêmes modifications reviennent.
la source
Vous pouvez suivre ces étapes pour rétablir les validations incorrectes ou pour réinitialiser votre branche distante à l'état HEAD / état correct.
git checkout development
copier le hachage de validation (c'est-à-dire l'identifiant de la validation immédiatement avant la mauvaise validation) depuis le journal git
git log -n5
réinitialiser la branche sur le hachage de validation copié à l'étape précédente
git reset <commit-hash> (i.e. 3779ab50e72908da92d2cfcd72256d7a09f446ba)
git status
pour afficher toutes les modifications qui faisaient partie du mauvais commit.git reset --hard
pour annuler tous ces changements.git push -f origin development
la source
la source
Pour garder le journal propre car rien ne s'est passé (avec quelques inconvénients avec cette approche (en raison de push -f)):
'commit-hash-before-merge' provient du journal (git log) après la fusion.
la source
push -f
repo partagéParfois, le moyen le plus efficace de revenir en arrière consiste à prendre du recul et à remplacer.
git log
Utilisez le 2e hachage de validation (hachage complet, celui auquel vous souhaitez revenir avant l'erreur répertoriée), puis rebranchez-le à partir de là.
git checkout -b newbranch <HASH>
Supprimez ensuite l'ancienne branche, copiez la nouvelle branche à sa place et redémarrez à partir de là.
Si elle a été diffusée, supprimez l'ancienne branche de tous les référentiels, poussez la branche refaite vers la plus centrale et ramenez-la vers le bas pour toutes.
la source
Si vous souhaitez annuler un
merge
commit, voici ce que vous devez faire.git log
pour trouver l'ID de votre commit de fusion. Vous trouverez également plusieurs identifiants parents associés à la fusion (voir l'image ci-dessous).Notez l'ID de validation de fusion affiché en jaune. Les ID parents sont ceux écrits sur la ligne suivante sous la forme
Merge: parent1 parent2
. Maintenant...Histoire courte:
git revert <merge commit id> -m 1
qui ouvrira unevi
console pour entrer le message de validation. Écrivez, enregistrez, quittez, c'est fait!Longue histoire:
Basculez vers la branche sur laquelle la fusion a été effectuée. Dans mon cas, c'est la
test
branche et j'essaie d'en supprimer lafeature/analytics-v3
branche.git revert
est la commande qui annule tout commit. Mais il y a une mauvaise astuce lors de l'annulation d'unmerge
commit. Vous devez entrer le-m
drapeau sinon il échouera. À partir de là, vous devez décider si vous souhaitez rétablir votre branche et la faire ressembler exactement à ce qu'elle était surparent1
ouparent2
via:git revert <merge commit id> -m 1
(revient àparent2
)git revert <merge commit id> -m 2
(revient àparent1
)Vous pouvez enregistrer ces parents pour savoir dans quelle direction vous voulez aller et c'est la racine de toute la confusion.
la source
Toutes les réponses couvraient déjà la plupart des choses, mais j'ajouterai mes 5 cents. En bref, annuler un commit de fusion est assez simple:
Si vous en avez la permission, vous pouvez le pousser directement vers la branche "master", sinon il vous suffit de le pousser vers votre branche "revert" et de créer une requête pull.
Vous trouverez peut-être des informations plus utiles à ce sujet ici: https://itcodehub.blogspot.com/2019/06/how-to-revert-merge-in-git.html
la source
J'ai trouvé que la création d'un patch inverse entre deux points d'extrémité connus et l'application de ce patch fonctionneraient. Cela suppose que vous avez créé des instantanés (balises) à partir de votre branche principale ou même une sauvegarde de votre branche principale, par exemple master_bk_01012017.
Supposons que la branche de code que vous avez fusionnée dans master soit mycodebranch.
git diff --binary master..master_bk_01012017 > ~/myrevert.patch
git apply --check myrevert.patch
git am --signoff < myrevert.patch
git branch mycodebranch_fix
git checkout mycodebranch_fix
git revert [SHA]
la source
La réponse correctement marquée a fonctionné pour moi mais j'ai dû passer un peu de temps à déterminer ce qui se passait .. J'ai donc décidé d'ajouter une réponse avec des étapes simples pour des cas comme le mien ..
Disons que nous avons obtenu les branches A et B .. Vous avez fusionné la branche A dans la branche B et poussé la branche B vers elle-même alors maintenant la fusion en fait partie .. Mais vous voulez revenir au dernier commit avant la fusion .. Que faire tu fais?
git log
Vous verrez l'historique des validations récentes - les validations ont des propriétés commit / author / date tandis que les fusions ont également une propriété merge - donc vous les voyez comme ceci:
commit: <commitHash> Merge: <parentHashA> <parentHashB> Author: <author> Date: <date>
Utilisez
git log <parentHashA>
etgit log <parentHashB>
- vous verrez les historiques de validation de ces branches parentes - les premiers validations de la liste sont les plus récentes<commitHash>
commit que vous voulez, allez dans votre dossier racine git et utilisezgit checkout -b <newBranchName> <commitHash>
- cela créera une nouvelle branche à partir du dernier commit que vous avez choisi avant la fusion .. Voila, prêt!la source
git doc sur git revert -m fournit un lien expliquez exactement ceci: https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt
la source
J'ai également rencontré ce problème sur un PR qui a été fusionné avec la branche principale d'un dépôt GitHub.
Depuis que je voulais juste modifier quelques fichiers modifiés , mais pas tout change PR apporté, je devais
amend
lemerge commit
avecgit commit --am
.Pas:
git add *
ougit add <file>
git commit --am
et validergit push -f
Pourquoi c'est intéressant:
la source
J'ai trouvé une bonne explication pour annuler la fusion à partir de ce lien et j'ai copié collé l'explication ci-dessous et il serait utile au cas où le lien ci-dessous ne fonctionne pas.
Comment annuler une fusion défectueuse Alan ([email protected]) a déclaré:
J'ai une branche principale. Nous avons une branche sur laquelle certains développeurs travaillent. Ils prétendent qu'il est prêt. Nous le fusionnons dans la branche principale. Il casse quelque chose donc nous revenons à la fusion. Ils apportent des modifications au code. ils parviennent à un point où ils disent que c'est ok et nous fusionnons à nouveau. Une fois examinés, nous constatons que les modifications de code effectuées avant le retour ne sont pas dans la branche principale, mais les modifications de code après sont dans la branche principale. et a demandé de l'aide pour se remettre de cette situation.
L'histoire immédiatement après le "retour de la fusion" ressemblerait à ceci:
où A et B sont sur le développement latéral qui n'était pas si bon, M est la fusion qui apporte ces changements prématurés dans la ligne principale, x sont des changements sans rapport avec ce que la branche latérale a fait et déjà effectués sur la ligne principale, et W est le " annuler la fusion M "(W ne regarde-t-il pas M à l'envers?). IOW, "diff W ^ .. W" est similaire à "diff -RM ^ .. M".
Un tel "retour" d'une fusion peut être effectué avec:
$ git revert -m 1 M Une fois que les développeurs de la branche latérale ont corrigé leurs erreurs, l'historique peut ressembler à ceci:
où C et D doivent réparer ce qui a été cassé en A et B, et vous pouvez déjà avoir d'autres changements sur la ligne principale après W.
Si vous fusionnez la branche latérale mise à jour (avec D à son extrémité), aucune des modifications apportées dans A ou B ne sera dans le résultat, car elles ont été annulées par W. C'est ce qu'Alan a vu.
Linus explique la situation:
La restauration d'un commit régulier annule simplement ce que ce commit a fait et est assez simple. Mais l'annulation d'un commit de fusion annule également les données modifiées par le commit, mais cela n'a absolument rien à voir avec les effets sur l' historique de la fusion. Ainsi, la fusion existera toujours, et elle sera toujours considérée comme joignant les deux branches, et les futures fusions verront cette fusion comme le dernier état partagé - et le retour qui a annulé la fusion apportée n'affectera pas du tout cela. Donc, un "retour" annule les modifications de données, mais ce n'est pas du tout un "défaire" dans le sens où il n'annule pas les effets d'un commit sur l'historique du référentiel. Donc, si vous pensez à "revenir" comme "annuler", alors vous allez toujours manquer cette partie des retours. Oui, cela annule les données, mais non, il n'annule pas l'historique. Dans une telle situation, vous voudrez d'abord revenir à la précédente, ce qui donnerait à l'histoire l'aspect suivant:
où Y est le retour de W. Un tel "retour du retour" peut se faire avec:
$ git revert W Cet historique (en ignorant les conflits possibles entre ce que W et W..Y ont changé) équivaudrait à ne pas avoir du tout W ou Y dans l'historique:
et la fusion à nouveau de la branche latérale n'aura pas de conflit résultant d'un retour antérieur et d'un retour du retour.
Bien sûr, les modifications apportées en C et D peuvent toujours entrer en conflit avec ce qui a été fait par l'un des x, mais ce n'est qu'un conflit de fusion normal.
la source
Comme Ryan l'a mentionné, cela
git revert
pourrait rendre la fusion difficile sur la route, donc cegit revert
n'est peut-être pas ce que vous voulez. J'ai trouvé que l'utilisation de lagit reset --hard <commit-hash-prior-to-merge>
commande était plus utile ici.Une fois que vous avez terminé la partie de réinitialisation matérielle, vous pouvez alors forcer le push vers la branche distante, c'est
git push -f <remote-name> <remote-branch-name>
-à- dire où<remote-name>
est souvent nomméorigin
. À partir de là, vous pouvez refusionner si vous le souhaitez.la source