Pourquoi la signification de «notre» et «leurs» est-elle inversée avec git-svn?

J’utilise git-svn et j’ai remarqué que lorsque je dois résoudre un conflit de fusion après avoir effectué un git svn rebase , la signification des options --ours et --theirs pour, par exemple, --theirs git checkout est inversée. En d’autres termes, s’il ya un conflit et que je veux conserver la version fournie par le serveur SVN et rejeter les modifications apscopes localement, je dois utiliser le ours , alors que je m’attendrais à ce que ce soit le theirs .

Pourquoi donc?

Exemple:

 mkdir test cd test svnadmin create svnrepo svn co file://$PWD/svnrepo svnwc cd svnwc echo foo > test.txt svn add test.txt svn ci -m 'svn commit 1' cd .. git svn clone file://$PWD/svnrepo gitwc cd svnwc echo bar > test.txt svn ci -m 'svn commit 2' cd .. cd gitwc echo baz > test.txt git commit -a -m 'git commit 1' git svn rebase git checkout --ours test.txt cat test.txt # shows "bar" but I expect "baz" git checkout --theirs test.txt cat test.txt # shows "baz" but I expect "bar" 

Cela semble cohérent avec ce que fait une rebase.

  • git svn rebase va chercher les révisions du parent SVN du HEAD actuel et rebasonne le travail actuel (non engagé sur SVN).

  • git rebase mentionne:
    Notez qu’une fusion par fusion fonctionne en relisant chaque validation depuis la twig de travail située au-dessus de la twig .
    De ce fait, lorsqu’un conflit de fusion se produit:

    • le côté signalé comme le nôtre est la série rebasée jusqu’ici, en commençant par ,
    • et la leur est la twig de travail .
      En d’autres termes, les côtés sont échangés .

git rebase relit chaque commit de la twig de travail en haut de la twig .

Si vous réconciliez les deux définitions:

  • les commits provenant de SVN sont ceux au-dessus desquels les commits Git locaux sont rejoués. Ils font partie de la série “rebasée jusqu’ici” et sont référencés comme “notre” (dans votre cas, le fichier test.txt avec le contenu de la bar )
  • la twig de travail (contenant les commits Git inconnus de SVN, dans votre cas, le fichier test.txt avec le contenu baz ) est “leur”, et chacun de ces commits Git locaux est en cours de relecture.

En d’autres termes, SVN ou non:

  • la twig ” ” (au-dessus de laquelle tout est rejoué, et qui fait partie des commits rebasés à ce jour “) est” la nôtre “.
  • ce qui est rejoué (la twig de travail) est “le leur “.

Bon conseil mnémonique par CommaToast :

tout ce que HEAD a désigné est “le nôtre”

(et la première chose qu’une git rebase upstream la twig en upstream au-dessus de laquelle vous voulez rebaser: HEAD fait référence à la twig en upstream – la ours maintenant.)


La confusion vient probablement du rôle de la twig de travail dans une git merge classique.
Lorsque vous fusionnez:

  • la “twig de travail” est celle qui contient ce qui est “jusqu’ici fusionné” et qui est considérée comme “notre”,
  • tandis que l’autre commit représente ce qui est – non rejoué mais – fusionne au-dessus de la twig de travail et considéré comme “leur”.

Comme le mentionne la page de git rebase , une fusion lors d’un rebase signifie que le côté est échangé.


Une autre façon de dire la même chose est de considérer que:

  • ce que nous avons sur la twig empruntée est «la nôtre »,
  • ce que nous avions (et que nous fusionnons ou rejouons) est «le leur ».

Sur une fusion :

 x--x--x--x--x(*) <- current branch B ('*'=HEAD) \ \ \--y--y--y <- other branch to merge 

, nous ne changeons pas la twig actuelle 'B', alors ce que nous avons est toujours ce sur quoi nous travaillions (et nous fusionnons depuis une autre twig)

 x--x--x--x--x---------o(*) MERGE, still on branch B \ ^ / \ ours / \ / --y--y--y--/ ^ their 

Mais sur une rebase , nous changeons de côté car la première chose que fait une rebase est de vérifier la twig en amont! (pour rejouer les commits actuels)

 x--x--x--x--x(*) <- current branch B \ \ \--y--y--y <- upstream branch 

Un git rebase upstream changera d'abord HEAD de B en HEAD amont (d'où le changement de 'ours' et de 'leurs' par rapport à la twig de travail précédente "en cours").

 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 la rebase rejouera 'leurs' commits sur la nouvelle 'notre' twig 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 

La seule étape supplémentaire avec git svn rebase est qu’un svn "fetch" est exécuté d’abord sur la twig distante de Git représentant les commits SVN.
Vous avez au départ:

 x--x--x--x--x(*) <- current branch B, "ours" for now. \ \ \--y--y--y <- SVN tracking branch, "theirs for now" 

, vous mettez d'abord à jour la twig de suivi SVN avec les nouveaux commits provenant de SVN

 x--x--x--x--x(*) <- current branch B, still "ours", not for long \ \ \--y--y--y--y'--y' <- SVN tracking branch updated 

, alors vous basculez la twig actuelle vers le côté SVN (qui devient "notre")

 x--x--x--x--x <- for "B", now "their" during the rebase \ \ \--y--y--y--y'--y'(*) <- SVN tracking branch updated, and branch B: now "ours" (this is "what we now have") 

, avant de rejouer les commits sur lesquels vous travailliez (mais qui sont maintenant "les leurs" lors de cette rebase)

 x--x..x..x..x <- old "theirs" commits, now "ghosts", available through reflogs \ \ \--y--y--y--y'--y'--x'--x'--x'(*) <- branch B with HEAD updated ("ours") ^ | upstream SVN tracking branch