git rebase, garder une trace de ' local 'et'remote'
Lorsque je fais un rebase git, j'ai souvent du mal à comprendre ce qui se passe avec le 'local' et le 'remote' lors de la résolution des conflits. J'ai parfois l'impression qu'ils s'échangent des côtés d'un commit à la prochaine.
C'est probablement (définitivement) parce que je n'ai toujours pas bien compris.
Lors du rebasage, qui est 'local' et qui est 'distant'?
(j'utilise P4Merge pour résoudre les conflits)
3 réponses
TL; DR;
Pour résumer (Comme Benubird commentaires), alors:
git checkout A
git rebase B # rebase A on top of B
-
local
estB
(rebase sur), -
remote
estA
Et:
git checkout A
git merge B # merge B into A
-
local
estA
(fusion dans), -
remote
estB
Un rebase change ours
(branche actuelle avant le début du rebase) et theirs
(branche au-dessus de laquelle vous voulez rebaser).
Kutschkem souligne que, dans une interface graphique, mergetool contexte:
-
références locales les validations partiellement rebasées: "
ours
" (la branche amont) -
remote fait référence aux modifications entrantes: "
theirs
" - la branche actuelle avant le rebase.
Voir les illustrations dans la dernière partie de cette réponse.
Inversion quand rebase
, La confusion pourrait être liée à la inversion de ours
et theirs
lors d'un rebase.
(extraits pertinents)
Notez qu'une fusion de rebase fonctionne en rejouant chaque commit de la branche de travail au - dessus de la branche
<upstream>
.
Pour cette raison, quand un conflit de fusion se produit:
- le côté rapporté comme '
ours
' est la série rebasée jusqu'à présent, en commençant par<upstream>
, - et '
theirs
' est la branche de travail. Dans d'autres les mots, les côtés sont inversés.
Inversion illustrée
Sur une fusion
x--x--x--x--x(*) <- current branch B ('*'=HEAD)
\
\
\--y--y--y <- other branch to merge
, Nous ne changeons pas la branche courante 'B', donc ce que nous avons est toujours ce sur quoi nous travaillions (et nous fusionnons à partir d'une autre branche)
x--x--x--x--x---------o(*) MERGE, still on branch B
\ ^ /
\ ours /
\ /
--y--y--y--/
^
their
Sur un rebase:
Mais sur un rebase , nous changeons de côté car la première chose qu'un rebase fait est de récupérer la branche amont! (pour rejouer les commits en cours)
x--x--x--x--x(*) <- current branch B
\
\
\--y--y--y <- upstream branch
Un git rebase upstream
va d'abord changer HEAD
de B à la branche amont HEAD
(d'où le commutateur de 'nôtre' et 'leur' par rapport à la branche de travail "actuelle" précédente.)
x--x--x--x--x <- former "current" branch, new "theirs"
\
\
\--y--y--y(*) <- upstream branch with B reset on it,
new "ours", to replay x's on it
, puis le rebase rejouera 'leurs' commits sur la nouvelle branche' notre ' B:
x--x..x..x..x <- old "theirs" commits, now "ghosts", available through reflogs
\
\
\--y--y--y--x'--x'--x'(*) <- branch B with HEAD updated ("ours")
^
|
upstream branch
Note: la notion "amont" est l'ensemble référentiel de données (un tout repo ou, comme ici, une branche, qui peut être uneLocal branche) à partir de laquelle les données sont lues ou vers lesquelles les nouvelles données sont ajout/création.
'local
' et 'remote
' vs. 'mine
' et 'theirs
'
Pandawood ajoute dans les commentaires:
Pour moi, la question demeure, qui est "local" et qui est "distant" (puisque les Termes "nôtre" et "leur" ne sont pas utilisés lors du rebasage dans git, leur référence semble juste rendre une réponse plus confuse).
GUI git mergetool
Kutschkem ajoute, et à juste titre donc:
Lors de la résolution des conflits, git dira quelque chose comme:
local: modified file and remote: modified file.
Je suis tout à fait sûr que la question vise à la définition de local et distant à ce stade. À ce stade, il me semble d'après mon expérience que:
-
références locales les validations partiellement rebasées: "
ours
" (la branche amont) -
remote fait référence aux modifications entrantes: "
theirs
" - la branche actuelle avant le rebase.
git mergetool
mentionne en effet "local" et "distant':
Merging:
f.txt
Normal merge conflict for 'f.txt':
{local}: modified file
{remote}: modified file
Hit return to start merge resolution tool (kdiff3):
Par exemple, KDiff3 affichera la résolution de fusion comme ceci :
Et fondre serait afficher trop:
De Même pour VimDiff, qui affiche:
Appelez Vimdiff en tant que mergetool avec git mergetool-t gvimdiff. Versions récentes de Git invoke Vimdiff avec la disposition de fenêtre suivante:
+--------------------------------+
| LOCAL | BASE | REMOTE |
+--------------------------------+
| MERGED |
+--------------------------------+
LOCAL
:
Un fichier temporaire contenant le contenu du fichier sur la branche courante.BASE
:
Fichier temporaire contenant la base commune de la fusion.REMOTE
:
Un fichier temporaire contenant le contenu du fichier fusionné.MERGED
:
Le fichier contenant les marqueurs de conflit.Git a effectué autant de résolution automatique de conflit que possible et l'état de ce fichier est une combinaison de
LOCAL
etREMOTE
avec des marqueurs de conflit entourant tout ce que Git n'a pas pu résoudre lui-même.
Le {[45] } doit écrire le résultat de la résolution dans ce fichier.
La ligne du bas
Git rebase
- LOCAL = La base que vous rebasez sur
- REMOTE = les commits que vous déplacez en haut
Git merge
- LOCAL = la branche d'origine dans laquelle vous fusionnez
- REMOTE = l'autre branche dont vous fusionnez les commits
En d'autres termes, LOCAL est toujours l'original, et à DISTANCE est toujours le type qui s'engage n'étaient pas là avant, parce qu'ils sont fusionnés ou rebasés en haut
Prouvez-le!
Certainement. Ne prenez pas mon mot pour lui! Voici une expérience facile que vous pouvez faire pour voir par vous-même.
Tout d'abord, assurez-vous que git mergetool est correctement configuré. (Si vous ne l'avez pas fait, vous ne lirez probablement pas cette question de toute façon.) Ensuite, trouvez un répertoire dans lequel travailler.
Configurez votre référentiel:
md LocalRemoteTest
cd LocalRemoteTest
Crée un commit initial (avec un fichier):
git init
notepad file.txt (use the text editor of your choice)
(save the file as an empty file)
git add -A
git commit -m "Initial commit."
Créez un commit sur une branche qui n'est pas maître:
git checkout -b notmaster
notepad file.txt
(add the text: notmaster)
(save and exit)
git commit -a -m "Add notmaster text."
Créez un commit sur la branche master:
git checkout master
notepad file.txt
(add the text: master)
(save and exit)
git commit -a -m "Add master text."
gitk --all
À ce stade, votre référentiel devrait ressembler à ceci:
Maintenant pour le test de rebase:
git checkout notmaster
git rebase master
(you'll get a conflict message)
git mergetool
LOCAL: master
REMOTE: notmaster
Maintenant, le test de fusion. Fermez votre mergetool sans enregistrer les modifications, puis annulez le rebase:
git rebase --abort
Puis:
git checkout master
git merge notmaster
git mergetool
LOCAL: master
REMOTE: notmaster
git reset --hard (cancels the merge)
Vos résultats devraient être les mêmes que ceux affichés en haut.
Je n'ai pas eu votre problème exactement mais je pense que le diagramme suivant résout votre problème. (Rebase: Référentiel Distant - - - > Espace De Travail)
Source: Mon Flux De Travail Git