Nous avons tous entendu dire qu'il ne faut jamais rebaser un travail publié, que c'est dangereux, etc. Cependant, je n'ai vu aucune recette publiée pour savoir comment gérer la situation au cas où un rebase serait publié.
Maintenant, notez que cela n'est vraiment faisable que si le référentiel n'est cloné que par un groupe de personnes connu (et de préférence petit), de sorte que quiconque pousse le rebase 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 foo
et qu'elle est rebasée:
git fetch
git checkout foo
git reset --hard origin/foo
Cela rejettera simplement l'état local de foo
au profit de son histoire selon le référentiel distant.
Mais comment gérer la situation si l'on a engagé des changements locaux substantiels sur cette branche?
la source
git pull --rebase && git push
. Si vous travaillezmaster
uniquement sur , cela fera presque toujours la bonne chose pour vous, même si vous avez rebasé et poussé à l'autre bout.git reset --hard @{upstream}
maintenant que je sais que l'incantation magique de refspec pour "oubliez ce que j'ai / j'avais, utilisez ce que j'ai récupéré de la télécommande" Voir mon dernier commentaire sur stackoverflow.com/a/15284176/717355push -f
): voir ma réponse ciRéponses:
Se remettre en synchronisation après un rebase poussé n'est vraiment pas si compliqué dans la plupart des cas.
C'est à dire. vous configurez d'abord un signet pour l'emplacement d'origine de la branche distante, puis vous l'utilisez pour rejouer vos commits locaux à partir de ce point sur la branche distante rebasée.
Rebasing est comme la violence: si cela ne résout pas votre problème, vous en avez juste besoin de plus. ☺
Vous pouvez le faire sans le signet bien sûr, si vous recherchez l'
origin/foo
ID de validation pré-rebase et que vous l'utilisez.C'est également ainsi que vous gérez la situation où vous avez oublié de créer un signet avant de le récupérer. Rien n'est perdu - il vous suffit de vérifier le reflog de la branche distante:
Cela affichera l'ID de validation qui
origin/foo
pointait avant la dernière extraction qui a changé son historique.Vous pouvez alors simplement
la source
git reflog show origin/foo
la première ligne en disant "fetch: forcé-mise à jour"; c'est ce que git enregistre lorsqu'une extraction amène la branche distante à faire autre chose qu'une avance rapide. (Vous pouvez aussi le faire à la main - la mise à jour forcée est probablement la chose la plus récente.)Je dirais que la récupération à partir de la section rebase en amont de la page de manuel git-rebase couvre à peu près tout cela.
Ce n'est vraiment pas différent de la récupération de votre propre rebase - vous déplacez une branche et rebasez toutes les branches qui l'avaient dans leur histoire sur sa nouvelle position.
la source
A partir de git 1.9 / 2.0 Q1 2014, vous ne devez marquer l' origine précédente de la branche avant rebasage sur la branche amont réécrite, comme décrit dans Aristote Pagaltzis de réponse :
Voir commit 07d406b et engage d96855f :
C'est pourquoi la
git merge-base
commande a une nouvelle option:Par exemple, si l'historique ressemblait à où:
Git 2.1 (Q3 2014) ajoutera pour rendre cette fonctionnalité plus robuste à ceci: voir commit 1e0dacd par John Keeping (
johnkeeping
)gérer correctement le scénario où nous avons la topologie suivante:
où:
B'
est une version corrigée deB
qui n'est pas identique au patchB
;C*
etD*
sont identiques au patchC
etD
respectivement et sont en conflit textuellement s'ils sont appliqués dans le mauvais ordre;E
dépend textuellement deD
.Le résultat correct de
git rebase master dev
est - ce queB
est identifié comme le point fourchedev
etmaster
, de sorte queC
,D
,E
sont les commits qui doivent être rejoué surmaster
; maisC
etD
sont identiques au patch avecC*
andD*
et peuvent donc être supprimés, de sorte que le résultat final est:Si le point de bifurcation n'est pas identifié, alors choisir
B
une branche contenantB'
entraîne un conflit et si les commits identiques au correctif ne sont pas correctement identifiés, alors choisirC
une branche contenantD
(ou de manière équivalenteD*
) entraîne un conflit.Le "
--fork-point
" mode de "git rebase
" a régressé lorsque la commande a été réécrite en C à l'ère 2.20, ce qui a été corrigé avec Git 2.27 (T2 2020).Voir commit f08132f (09 décembre 2019) par Junio C Hamano (
gitster
) .(Fusionné par Junio C Hamano -
gitster
- dans commit fb4175b , 27 mars 2020)la source