tl;dr Vous devez mettre à jour les deux master
y feature
con git pull
y git pull --rebase
avant rebasement feature
sur le dessus de master
. Il n'est pas nécessaire de faire un git pull
après vous avez rebasé votre feature
sur le dessus de master
.
Avec votre flux de travail actuel, la raison pour laquelle git status
vous dit ça :
Votre branche et votre "origine/caractéristique" ont divergé, et ont chacune 27 et 2 commits différents, respectivement.
c'est parce que votre rebasement feature
La branche a maintenant 25 de nouveaux commits qui ne sont pas accessibles à partir de origin/feature
(puisqu'ils proviennent de la rebase sur master
) plus 2 s'engage à ce que sont accessible à partir de origin/feature
mais ont des identifiants de livraison différents. Ces commits contiennent les mêmes changements (c'est-à-dire qu'ils sont équivalent de patch ) mais ils ont des hachages SHA-1 différents parce qu'ils sont basés sur un commit différent dans le fichier origin/feature
que celui sur lequel vous les avez rebasés dans votre référentiel local.
Voici un exemple. Supposons que votre historique soit le suivant avant en faisant git pull
sur master
:
A - B - C (master)
\
D - E (feature)
Après git pull
, master
a obtenu un engagement F
:
A - B - C - F (master, origin/master)
\
D - E (feature)
A ce moment-là, vous rebasez feature
sur le dessus de master
qui s'applique D
y E
:
A - B - C - F (master, origin/master)
\
D - E (feature)
Pendant ce temps, la branche distante origin/feature
est toujours basé sur le commit C
:
A - B - C - F (master, origin/master)
\ \
\ D' - E' (feature)
\
D - E (origin/feature)
Si vous faites un git status
sur feature
Git vous dira que votre feature
a divergé de origin/feature
con 3 ( F
, D'
, E'
) et 2 ( D
, E
), respectivement.
Notez que D'
y E'
contiennent les mêmes modifications que D
y E
mais ont des identifiants de livraison différents parce qu'ils ont été refondus au dessus de F
.
La solution consiste à faire git pull
sur les deux master
y feature
avant rebasement feature
sur master
. Cependant, comme vous pouvez avoir des commits sur feature
que vous n'avez pas encore poussé vers origin
que tu voudrais faire :
git checkout feature && git pull --rebase
pour éviter de créer un fusionner commettre entre origin/feature
et votre feature
.
Le point sur les conséquences du rebasage :
À la lumière de ce commentaire je me suis étendu sur les branches divergentes. La raison pour laquelle git status
rapporte que feature
y origin/feature
diverger après le rebasement est dû au fait que le rebasement apporte de nouveaux commits à la base de données. feature
De plus, il réécrites les commits qui ont été précédemment poussés vers origin/feature
.
Considérez la situation après l'attraction mais avant le rebasement :
A - B - C - F (master)
\
D - E (feature, origin/feature)
A ce stade, feature
y origin/feature
pointent vers le même commit E
-en d'autres termes, ils sont dans " sync ". Après avoir rebasé feature
sur le dessus de master
l'histoire ressemblera à ça :
A - B - C - F (master)
\ \
\ D' - E' (feature)
\
D - E (origin/feature)
Comme vous pouvez le voir, feature
y origin/feature
ont divergent leur ancêtre commun étant l'engagement C
. Cela s'explique par le fait que feature
contient maintenant le nouveau commit F
de master
plus D'
y E'
(lu comme " D prime " et " E prime ") qui sont des engagements D
y E
appliqué sur le dessus de F
. Bien qu'ils contiennent les mêmes modifications, Git les considère comme différents car ils ont des ID de commit différents. En attendant, origin/feature
références fixes D
y E
.
A ce stade, vous avez histoire réécrite vous avez modifié des commits existants en les rebasant, créant ainsi de "nouveaux" commits.
Maintenant, si tu devais exécuter git pull
sur feature
c'est ce qui se passerait :
A - B - C - F (master)
\ \
\ D' - E'- M (feature)
\ /
D - E - (origin/feature)
Depuis git pull
fait git fetch
+ git merge
ce qui entraînerait la création du commit de fusion. M
dont les parents sont E'
y E
.
Si, à la place, vous avez exécuté git pull --rebase
(c'est-à-dire, git fetch
+ git rebase
) alors Git le ferait :
- Déplacements
feature
de s'engager C
(l'ancêtre commun de feature
y origin/feature
)
- Appliquer
D
y E
de origin/feature
- Appliquer
F
, D'
y E'
Cependant, en remarquant que D'
y E'
contiennent les mêmes modifications que D
y E
Git les rejetterait tout simplement, ce qui donnerait un historique ressemblant à ceci :
A - B - C - F (master)
\
D - E - F' (feature)
^
(origin/feature)
Remarquez comment l'engagement F
, précédemment accessible à partir de feature
a été appliqué sur le dessus de origin/feature
ce qui entraîne F'
. A ce stade, git status
vous dirait ceci :
Votre branche est en avance sur 'origin/feature' de 1 commit.
Cet engagement étant, bien sûr, F'
.