Comment puis-je récupérer / resynchroniser après que quelqu'un pousse un rebasage ou une réinitialisation à une branche publiée?

StackOverflow https://stackoverflow.com/questions/4084868

Question

Nous avons tous entendu que l'on ne devrait jamais le travail publié rebasage, qu'il est dangereux, etc. Cependant, je ne l'ai pas vu de recettes affichées sur la façon de faire face à la situation au cas où un rebasage publié .

Maintenant, ne note que ce n'est vraiment possible que si le dépôt est uniquement cloné par un groupe connu (et de préférence faible) de personnes, de sorte que celui qui pousse le rebasage ou remise à zéro peut informer tout le monde qu'ils devront faire attention prochaine fois qu'ils fetch (!).

Une solution évidente que je l'ai vu fonctionnera si vous n'avez pas commits locaux sur foo et il devient rebasées:

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

Ce sera tout simplement jeter l'état local de foo en faveur de son histoire par le dépôt distant.

Mais comment peut-on face à la situation si l'on a engagé des changements locaux importants sur cette branche?

Était-ce utile?

La solution

Pour revenir en phase après un rebasage poussé est vraiment pas si compliqué que ça 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

Ie. D'abord, vous configurez un signet pour lequel la branche à distance était à l'origine, alors vous l'utiliser pour rejouer vos commits locaux partir de ce point sur la branche à distance rebasées.

rebasage est comme la violence: si elle ne résout pas votre problème, il vous suffit plus. ☺

Vous pouvez le faire sans le signet bien sûr, si vous regardez le pré-rebasage origin/foo commettez ID et utiliser.

Ceci est également la façon dont vous traitez avec la situation dans laquelle vous avez oublié de faire un signet avant aller chercher. Rien ne se perd - il vous suffit de vérifier la reflog pour la branche à distance:

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

imprimera la commettras ID qui origin/foo pointé avant la dernière lecture qui a changé son histoire.

Vous pouvez alors simplement

git rebase --onto origin/foo $commit foo

Autres conseils

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

Il est pas vraiment différent de récupérer de votre propre rebasage - vous déplacez une branche, et rebasage toutes les branches qu'il avait dans leur histoire sur sa nouvelle position

.

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 est réponse :
Voir engager 07d406b et commit d96855f :

  

Après avoir travaillé sur la branche topic créé avec git checkout -b topic origin/master, l'histoire de origin/master branche de suivi à distance peut-être rembobiné et reconstruit, conduisant à une histoire de cette forme:

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

origin/master utilisé pour point commits B3, B2, B1 et maintenant il pointe à B, et votre branche topic a été lancé au-dessus de celui-ci en arrière quand origin/master était à B3.

     

Ce mode utilise le reflog de origin/master pour trouver B3 comme point de fourchette, de sorte que le topic peut être rebasées au-dessus de la 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::
  

Trouver le point où une branche (ou toute l'histoire qui mène à <commit>) en forme de fourche d'une autre branche (ou toute référence) <ref>.
  Cela ne veut pas regarder juste pour l'ancêtre commun des deux commits, mais tient également compte de la reflog de <ref> pour voir si l'histoire menant à <commit> fourchue d'une incarnation antérieure de la branche <ref> .


  

La commande « git pull --rebase » calcule le point de fourche de la branche étant rebasées en utilisant les entrées reflog de la branche « base » (typiquement une branche de suivi à distance) du travail de la branche a été basée sur, en vue de faire face au cas qui la branche « de base » a été rembobiné et reconstruit.

Par exemple, si l'histoire ressemblait où:

  
      
  • l'extrémité actuelle de la branche « base » est à B, mais a observé que précédemment La récupération de la pointe utilisée pour être B3 puis B2 puis B1   avant d'arriver à la validation en cours et
  •   
  • la branche étant rebasées au-dessus de la dernière « base » est basée sur B3 engagement,
  •   
     

il essaie de trouver B3 en passant par la sortie de « git rev-list --reflog base » (à savoir B, B1, B2, B3) jusqu'à ce qu'il trouve un commit qui est un ancêtre de la pointe de courant « Derived (topic) ».

     

En interne, nous avons get_merge_bases_many() qui peut calculer cela avec un go.
  Nous voulons une fusion-base entre Derived et une fusion fictive commettras qui résulterait de la fusion de tous les conseils historiques de « base (origin/master) ».
  Lorsqu'un tel commit exist, nous devrions obtenir un seul résultat qui correspond exactement l'une des entrées de reflog « base ».


Git 2.1 (Q3 2014) ajoutera rendre cette fonctionnalité plus robuste à ce sujet: voir commettre 1e0dacd par John Keeping (johnkeeping)

gérer correctement le scénario dans lequel nousont la topologie suivante:

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

où:

  • B' est une version fixe d'B qui est patch identique pas B;
  • C* et D* sont patch-identique à C et D respectivement et les conflits si elle est appliquée textuellement dans le mauvais ordre;
  • E dépend textuellement sur D.

Le résultat correct de git rebase master dev est que B est identifié comme étant le point de la fourchette dev et master, de sorte que C, D, E sont les commits qui doivent être rejoué sur master; mais C et D sont patch-identique à C* et D* et peut donc être diminué, de sorte que le résultat final est le suivant:

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

Si le point de fourche est pas identifié, puis la cueillette B sur une branche contenant les résultats de B' dans un conflit et si les commits patch identiques ne sont pas correctement identifiés puis choisir C sur une branche contenant D (ou de manière équivalente D*) entraîne un conflit.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top