2010-11-20 22 views
4

historique Dans le scénario suivant:En git, l'édition d'un pré-pull engager après la traction provoque une divergence d'origine

  1. Marque engage A, B, C
  2. Pull, s'engage D, E
  3. Faire plus engage F, G, H, ...
  4. Rendez-vous compte que vous devez modifier B
  5. Tweak B à l'aide git rebase -i et git commit --amend

Maintenant git status dit:

Your branch and 'origin/master' have diverged. 

Comment dois-je résoudre ce problème?

Remarque: je n'ai pas poussé; cela n'a rien à voir avec pousser.

Remarque: Le simple fait de tirer à nouveau ne résout pas le problème; il recompose juste les commits D, E en plus de ce que j'ai déjà (bien que le D, E soit déjà là dans l'histoire), ce qui a aussi l'effet secondaire de produire des conflits superflus.

Pour élaborer, une réponse ci-dessous suggère que l'histoire est maintenant:

- A - B' - C' - F' - G' - H' (master) 
\ 
D - E (origin/master) 

Ce n'est pas tout à fait raison - il est en fait:

- A - B' - C' - D(?) - E(?) - F' - G' - H' (master) 
\ 
D - E (origin/master) 

Par conséquent, mon problème. Je voudrais que ce soit:

- A - B' - C' - F' - G' - H' (master) 
\  /
D - E (origin/master) 

Répondre

0

Note: Je n'accepterai pas ma propre réponse pendant un moment parce que je suis vraiment curieux à propos d'autres (meilleures) approches.

La façon dont je suis sorti de c'était à peine élégante:

# stash F, G, H - can't simply reorder them before D, E since they depend a lot on D, E 
for i in {1..3}; do git reset HEAD^; git stash; done 
# wipe out the weird non-merge D and E commits 
git reset --hard HEAD~2 
# pull to merge D, E again 
git pull 
# restore F, G, H 
for i in {1..3}; do git stash pop; git commit -a; done 
+1

Vous avez dit dans votre commentaire à ma réponse que D et E étaient déjà dans l'histoire, mais ici vous laissez entendre qu'ils ne le sont pas. Mais dans votre autre commentaire, vous avez également laissé entendre que vous utilisiez 'pull --rebase', ce qui signifierait que votre pull ici ne fusionne pas réellement. Je suis heureux d'essayer de vous trouver une meilleure réponse, et je suis sûr qu'il y en a une - si cela a fonctionné, il semble que tout ce que vous avez à faire est de vérifier, re-tirer, rebaser. Mais j'ai besoin de savoir exactement à quoi l'histoire ressemble pour donner une bonne réponse, et je ne suis pas trop confiant pour le moment. – Cascabel

+0

@Jefromi 'pull --rebase' n'est pas utilisé. D et E sont dans l'histoire, que j'ai anéanti avec la deuxième ligne. Je pense que ce que vous suggérez est une meilleure façon d'obtenir ce que j'ai fait ci-dessus, alors s'il vous plaît, éclairez-moi! – Yang

1

Je devine que vous n'avez pas utilisé l'option -p à git rebasage, ce qui signifie que la traction que vous avez fait, la fusion engage D et E, a été essuyée. Si c'est tout ce qui est arrivé, c'est simple: il suffit de tirer à nouveau. Si c'est ce qui s'est passé, votre histoire ressemblera à ceci:

- A - B' - C' - F' - G' - H' (master) 
\ 
D - E (origin/master) 

Il y a votre divergence!

Si vous avez préservez la fusion, alors ceci est tout à fait peut-être juste parce que quelque chose de nouveau a été poussé à l'origine dans l'intervalle:

- A - B' - C' - X' - F' - G' - H' (master) 
\   /
D - E -------- - Z (origin/master) 

et donc la solution, encore une fois, serait de tirer.

Si, toutefois, vous avez poussé quelque chose contenant le commit d'origine B, vous ne devriez pas avoir rebasé. Cela causera toujours des divergences, et ce n'est pas un amusement. Votre histoire ressemblerait à ceci:

B' - C' - F' - G' - H' (master) 
/
- A - B - C - X - F - G - H (origin/master) 
\   /
D - E ------ 

Il est un fait fondamental de la conception de git que le SHA1 d'un engagement dépend du SHA1 de son parent, et donc sur l'ensemble de la chaîne d'ascendance. C'est pourquoi après les rebasages, j'ai mis un "prime" sur tout. Même si vous n'avez pas modifié le contenu de C, la validation est modifiée.(L'autre possibilité, que vous ayez préservé la fusion, et poussé, devrait être inferrable comme une combinaison des deux dernières images.)

+0

+1, et "pas amusant" En effet, comme indiqué dans le paragraphe "[RECUPERATION DE AMONT REBASE] (http: // www. kernel.org/pub/software/scm/git/docs/git-rebase.html#_recovering_from_upstream_rebase) "de la page de manuel [' git rebase'] (http://www.kernel.org/pub/software/scm/ git/docs/git-rebase.html) ... – VonC

+0

Le simple fait de tirer à nouveau ne résout pas le problème; il ne fait que réappliquer les commits D, E au dessus de ce que j'ai déjà (bien que le D, E soit déjà là dans l'histoire), ce qui a aussi l'effet secondaire de produire des conflits superflus. Vous avez raison de ne pas utiliser '-p'; Je suis intéressé à réparer le statu quo étant donné que je n'ai pas utilisé '-p'. Aussi, je n'ai jamais poussé. – Yang

+1

@Yang: "il ne fait que réappliquer les commits D, E au dessus de ce que j'ai déjà" ce qui signifie que vous avez mis en place pour rebaser au lieu de fusionner? C'est une information très pertinente, et comme le dit la page de manuel: "C'est un mode de fonctionnement potentiellement dangereux ... N'utilisez pas cette option à moins d'avoir lu git-rebase (1) avec attention." – Cascabel