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:
, git rebase relit chaque commit de la twig de travail en haut de la twig
.
Si vous réconciliez les deux définitions:
test.txt
avec le contenu de la bar
) 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:
” (au-dessus de laquelle tout est rejoué, et qui fait partie des commits rebasés à ce jour “) est” la nôtre “. 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:
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:
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