Lors d'une refonte de git, j'ai souvent du mal à comprendre ce qui se passe avec le "local" et le "distant" lors de la résolution des conflits. J'ai parfois l'impression qu'ils changent de côté d'un commit à l'autre.
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)
Pour résumer (As Benubirdcomments ), quand:
git checkout A
git rebase B # rebase A on top of B
local
est B
(rebase sur ),remote
est A
Et:
git checkout A
git merge B # merge B into A
local
est A
(fusionner en ),remote
est B
Un rebase bascule ours
(branche courante avant le démarrage du rebase) et theirs
(la branche au dessus de laquelle vous voulez rebaser).
kutschkem souligne que, dans un contexte de mergetool GUI :
ours
" (la branche amont)theirs
" - la branche courante avant le rebase.Voir les illustrations dans la dernière partie de cette réponse.
La confusion peut être liée à inversion de ours
et theirs
lors d'un rebase .
(extraits pertinents)
Notez qu'une fusion de rebase fonctionne en relisant chaque commit à partir de la branche de travail en haut de
<upstream>
branche.
Pour cette raison, lorsqu'un conflit de fusion se produit:
ours
' est la série rebasée jusqu'à présent, commençant par <upstream>
,theirs
' est la branche de travail. En d'autres termes, les côtés sont échangés.x--x--x--x--x(*) <- current branch B ('*'=HEAD)
\
\
\--y--y--y <- other branch to merge
, nous ne changeons pas la branche actuelle '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
Mais sur un rebase , nous changeons de côté car la première chose qu'un rebase fait est de vérifier la branche en amont! (pour rejouer les validations actuelles par-dessus)
x--x--x--x--x(*) <- current branch B
\
\
\--y--y--y <- upstream branch
A git rebase upstream
changera d'abord HEAD
de B en la branche amont HEAD
(d'où le basculement de 'nôtre' et 'leur' par rapport au précédent "courant") "branche de travail.)
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 "notre" branche 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
Remarque: la notion "en amont" est l'ensemble référentiel de données (un tout repo ou, comme ici, une branche, qui peut être une locale branche) à partir de laquelle les données sont lues ou auxquelles de nouvelles données sont ajoutées/créées.
local
' et 'remote
' vs 'mine
' et 'theirs
'Pandawood ajoute les commentaires :
Pour moi, la question demeure, qui est "locale" et qui est "distante" (puisque les termes "les nôtres" et "les leurs" ne sont pas utilisés lors du rebasage en git, y faire référence semble simplement rendre la réponse plus confuse) .
kutschkem ajoute, et à juste titre:
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:
ours
" (la branche amont)theirs
" - la branche courante avant le rebase.git mergetool
mentionne en effet 'local' et 'remote' :
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, KDiff serait afficher la résolution de fusion comme ceci :
Et fusionner serait l'afficher aussi :
Idem pour VimDiff , qui affiche :
Appelez Vimdiff en tant que mergetool avec git mergetool -t gvimdiff. Les versions récentes de Git invoquent Vimdiff avec la disposition de fenêtre suivante:
+--------------------------------+
| LOCAL | BASE | REMOTE |
+--------------------------------+
| MERGED |
+--------------------------------+
LOCAL
:
Un fichier temporaire contenant le contenu du fichier sur la branche actuelle.BASE
:
Un fichier temporaire contenant la base commune pour la fusion.REMOTE
:
Un fichier temporaire contenant le contenu du fichier à fusionner.MERGED
:
Le fichier contenant les marqueurs de conflit.Git a effectué autant de résolution automatique des conflits 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.
Lemergetool
doit écrire le résultat de la résolution dans ce fichier.
La ligne du bas
git rebase
fusion git
En d'autres termes, [[# #]] local [~ # ~] est toujours l'original, et DISTANT est toujours le gars dont les engagements n'étaient pas là avant, car ils sont fusionnés ou rebasés au-dessus
Prouvez-le!
Certainement. Ne prenez pas ma parole pour ça! Voici une expérience simple que vous pouvez faire par vous-même.
Tout d'abord, assurez-vous que git mergetool est correctement configuré. (Si vous ne l'avez pas fait, vous ne liriez probablement pas cette question de toute façon.) Trouvez ensuite un répertoire dans lequel travailler.
Configurez votre référentiel:
md LocalRemoteTest
cd LocalRemoteTest
Créez un commit initial (avec un fichier vide):
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
Ensuite:
git checkout master
git merge notmaster
git mergetool
LOCAL: master
REMOTE: notmaster
git reset --hard (cancels the merge)
Vos résultats doivent être les mêmes que ceux affichés en haut.
Je n'ai pas compris exactement votre problème, 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