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)

139
demandé sur Benjol 2010-06-16 11:43:04

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 est B (rebase sur),
  • remote est A

Et:

git checkout A
git merge    B    # merge B into A
  • local est A (fusion dans),
  • remote est B

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)

git rebase page de manuel :

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 :

kdiff3

Et fondre serait afficher trop:

Meld diff

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 et REMOTE 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.

193
répondu VonC 2017-07-20 11:24:53

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:

Référentiel avec un commit de base et deux branches à un commit

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.

39
répondu Ryan Lundy 2014-05-02 18:41:38

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)

http://assets.osteele.com/images/2008/git-transport.png

Source: Mon Flux De Travail Git

3
répondu Chathuranga Chandrasekara 2016-04-27 21:15:26