web-dev-qa-db-fra.com

Pourquoi le sens du «nôtre» et du «leur» est-il inversé 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 du --ours et --theirs options pour par exemple git checkout est inversé. Autrement dit, s'il y a un conflit et que je souhaite conserver la version provenant du serveur SVN et supprimer les modifications que j'ai apportées localement, je dois utiliser ours, quand je m'attends à ce que ce soit 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"
89
Marc Liyanage

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

  • git svn rebase récupérera les révisions du parent SVN du courant HEAD et rebasera le travail courant (non engagé sur SVN) par rapport à lui.

  • git rebase mentionne:
    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:

    • le côté signalé comme le nôtre est la série rebasée jusqu'à présent, commençant par <upstream>,
    • et la leur est la branche de travail .
      En d'autres termes, les côtés sont inversés .

git rebase rejoue chaque commit à partir de la branche de travail en haut de <upstream> branche.

Si vous conciliez les deux définitions:

  • les validations provenant de SVN sont celles au-dessus desquelles les validations locales de Git sont rejouées. Ils font partie de la "série rebasée jusqu'à présent" et sont référencés comme "notre" (dans votre cas, le test.txt fichier avec bar contenu)
  • la branche de travail (contenant des commits Git inconnus de SVN, dans votre cas, le test.txt fichier avec baz contenu) est "leur", et chacun de ces commits Git locaux est en cours de relecture.

En d'autres termes, SVN ou non:

  • les "<upstream> "la branche (au dessus de laquelle tout est rejoué, et qui fait partie des commits rebasés jusqu'à présent") est " la nôtre ".
  • ce qui est rejoué (la branche de travail) est " le leur ".

Bon astuce mnémonique par CommaToast :

tout ce que HEAD pointe est "le nôtre"

(et la première chose qu'un git rebase upstream le fait pour extraire la branche upstream au dessus de laquelle vous souhaitez rebaser: HEAD fait référence à upstream - ours now .)


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

  • la "branche active" est celle contenant ce qui est "fusionné jusqu'à présent", et est considérée comme "notre",
  • tandis que les autres commit représentent ce qui est - non rejoué mais - fusionné au-dessus de la branche de travail, et considéré comme "leur".

Comme le git rebase page de manuel mentionne, 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 branche extraite est ' le nôtre ',
  • ce que nous avions (et qui est fusionné ou rejoué) est ' le leur '.

Lors d'une fusion :

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

La seule étape supplémentaire avec git svn rebase est qu'une "récupération" svn est effectuée en premier sur la branche distante Git représentant les validations SVN.
Vous avez initialement:

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 branche de suivi SVN avec de nouveaux commits venant de SVN

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

, puis vous basculez la branche actuelle du côté SVN (qui devient "la nôtre")

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 désormais "les leurs" lors de ce 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
225
VonC