Comment est-ce que je récupère / resynchronise après que quelqu’un ait poussé une rebase ou une réinitialisation à une twig publiée?

Nous avons tous entendu dire qu’il ne faut jamais rebuter les travaux publiés, que c’est dangereux, etc. Cependant, je n’ai vu aucune recette sur la manière de gérer la situation en cas de publication d’une rebase.

Maintenant, notez que cela n’est vraiment possible que si le référentiel est cloné uniquement par un groupe de personnes connu (et de préférence petit), afin que quiconque pousse la réinitialisation ou la réinitialisation puisse informer tout le monde qu’il devra faire attention la prochaine fois chercher (!).

Une solution évidente que j’ai vue fonctionnera si vous n’avez pas de commits locaux sur foo et qu’elle est rebasée:

 git fetch git checkout foo git reset --hard origin/foo 

Cela va simplement jeter l’état local de foo en faveur de son historique selon le référentiel distant.

Mais comment faire face à la situation si l’on a commis des changements locaux importants sur cette twig?

Se remettre en phase après un rebasement forcé n’est pas si compliqué dans la plupart des cas.

 git checkout foo git branch old-foo origin/foo # BEFORE fetching!! git fetch git rebase --onto origin/foo old-foo foo git branch -D old-foo 

C’est à dire. Tout d’abord, vous définissez un signet pour l’emplacement d’origine de la twig distante, puis vous l’utilisez pour relire vos commits locaux à partir de ce point sur la twig distante rebasée.

Rebaser est comme la violence: si cela ne résout pas votre problème, vous en avez juste besoin. ☺

Vous pouvez le faire sans le signet, bien sûr, si vous recherchez l’ID de validation d’ origin/foo pré-rebase et utilisez-le.

C’est également comme ça que vous traitez la situation où vous avez oublié de créer un signet avant de le récupérer. Rien n’est perdu – il suffit de vérifier le renvoi pour la twig distante:

 git reflog show origin/foo | awk ' PRINT_NEXT==1 { print $1; exit } /fetch: forced-update/ { PRINT_NEXT=1 }' 

Cela affichera l’identifiant de validation indiqué par l’ origin/foo avant la dernière extraction ayant modifié son historique.

Vous pouvez alors simplement

 git rebase --onto origin/foo $commit foo 

Je dirais que la section de récupération de l’amont de la page de manuel de git-rebase couvre à peu près tout cela.

Ce n’est vraiment pas différent de récupérer de votre propre rebase – vous déplacez une twig et rebassez toutes les twigs qui l’avaient dans leur histoire sur sa nouvelle position.

À partir de git 1.9 / 2.0 Q1 2014, vous ne devrez pas marquer votre origine de twig précédente avant de la rebaser sur la twig amont réécrite, comme décrit dans la réponse d’Aristotle Pagaltzis :
Voir commit 07d406b et commit d96855f :

Après avoir travaillé sur la twig de topic créée avec git checkout -b topic origin/master , l’historique de la twig de suivi à distance peut avoir été rembobiné et recréé, ce qui conduit à un historique de cette forme:

  o---B1 / ---o---o---B2--o---o---o---B (origin/master) \ B3 \ Derived (topic) 

origin/master utilisé pour indiquer les commits B3 , B2 , B1 et maintenant il pointe vers B , et votre twig de topic a été démarrée par-dessus lorsque l’ origin/master était à B3 .

Ce mode utilise le reflog d’ origin/master pour trouver B3 comme sharepoint fourche, de sorte que le topic puisse être rebasé sur l’ origin/master mis à jour par:

 $ fork_point=$(git merge-base --fork-point origin/master topic) $ git rebase --onto origin/master $fork_point topic 

C’est pourquoi la commande git merge-base a une nouvelle option:

 --fork-point:: 

Trouvez le point auquel une twig (ou tout historique qui conduit à ) est issue d’une autre twig (ou de toute référence) .
Cela ne se limite pas à rechercher l’ancêtre commun des deux commits, mais prend également en compte le reflet de pour voir si l’historique menant à issu d’une incarnation antérieure de la twig .


La commande ” git pull --rebase ” calcule le sharepoint fourche de la twig en cours de rebasage en utilisant les entrées de redissortingbution de la twig ” base ” (généralement une twig de suivi à distance) sur laquelle le travail de la twig a été effectué. dans lequel la twig “base” a été rembobinée et reconstruite.

Par exemple, si l’historique ressemblait à:

  • la pointe actuelle de la twig ” base ” est à B , mais la récupération précédente a observé que sa pointe était B3 puis B2 puis B1 avant de passer à la validation en cours, et
  • la twig rebasée au dessus de la dernière “base” est basée sur commit B3 ,

il essaye de trouver B3 en passant par la sortie de ” git rev-list --reflog base ” (c’est-à-dire B , B1 , B2 , B3 ) jusqu’à ce qu’il trouve un commit qui est un ancêtre de la pointe courante ” Derived (topic) ” .

En interne, nous avons get_merge_bases_many() qui peut le calculer avec un aller get_merge_bases_many() .
Nous voudrions une base de fusion entre Derived et un commit de fusion fictif qui résulterait de la fusion de tous les conseils historiques de ” base (origin/master) “.
Lorsqu’un tel commit existe, nous devrions obtenir un seul résultat, qui correspond exactement à l’une des entrées de reflex de ” base “.


Git 2.1 (Q3 2014) appenda plus de robustesse à cette fonctionnalité: voir commit 1e0dacd par John Keeping ( johnkeeping )

gérer correctement le scénario où nous avons la topologie suivante:

  C --- D --- E <- dev / B <- master@{1} / o --- B' --- C* --- D* <- master 

où:

  • B' est une version fixe de B qui n'est pas identique à B ;
  • C* et D* sont identiques à C et D respectivement, et à conflit textuel s'ils sont appliqués dans le mauvais ordre;
  • E dépend textuellement de D

Le résultat correct de git rebase master dev est que B est identifié comme le sharepoint départ de dev et master , de sorte que C , D , E sont les validations qui doivent être rejouées sur master ; mais C et D sont identiques à C* et D* et peuvent donc être supprimés, de sorte que le résultat final soit:

 o --- B' --- C* --- D* --- E <- dev 

Si le sharepoint fourche n'est pas identifié, le fait de choisir B sur une twig contenant B' crée un conflit et si les commits identiques au patch ne sont pas correctement identifiés, le choix de C sur une twig contenant D (ou D* équivalent) conflit.