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 avecgit 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)
où
origin/master
utilisé pour indiquer les commitsB3
,B2
,B1
et maintenant il pointe versB
, et votre twig detopic
a été démarrée par-dessus lorsque l’origin/master
était àB3
.Ce mode utilise le reflog d’
origin/master
pour trouverB3
comme sharepoint fourche, de sorte que letopic
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 depour 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 étaitB3
puisB2
puisB1
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-à-direB
,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 allerget_merge_bases_many()
.
Nous voudrions une base de fusion entreDerived
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.