¿Por qué se invierte el significado de "nuestro" y "de ellos" con git-svn?

Yo uso git-svn y noté que cuando tengo que arreglar un conflicto de fusión después de realizar una git svn rebase , el sentido de la --ours y --theirs opciones para, por ejemplo, git checkout se invierte. Es decir, si hay un conflicto y quiero conservar la versión que proviene del server SVN y deshacerme de los cambios que hice localmente, tengo que usar los ours , cuando esperaría que fueran los theirs .

¿Porqué es eso?

Ejemplo:

 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" 

Eso parece consistente con lo que hace una rebase.

  • git svn rebase obtendrá revisiones del padre SVN del HEAD actual y rebases el trabajo actual (no confirmado a SVN) en su contra.

  • git rebase menciona:
    Tenga en count que una fusión de rebase funciona al repetir cada confirmación desde la twig de trabajo en la parte superior de la twig <upstream> .
    Debido a esto, cuando ocurre un conflicto de fusión:

    • el lado reportado como el nuestro es la serie hasta ahora rebasada, comenzando con <upstream> ,
    • y la suya es la twig de trabajo .
      En otras palabras, los lados se intercambian .

git rebase reproduce cada confirmación desde la twig de trabajo en la parte superior de la twig <upstream> .

Si reconcilia ambas definiciones:

  • los commits provenientes de SVN son aquellos sobre los cuales se reproducen las confirmaciones locales de Git. Son parte de la "serie rebasada hasta ahora", y se mencionan como "nuestro" (en su caso, el file test.txt con contenido de bar )
  • la twig de trabajo (que contiene Git commits unknown to SVN, en su caso, el file test.txt con contenido baz ) es "their", y se están reproduciendo cada una de esas confirmaciones locales de Git.

En otras palabras, SVN o no:

  • la twig " <upstream> " (en la parte superior de la cual se reproduce cualquier cosa, y que es parte de las confirmaciones rebasadas hasta ahora) es " nuestra ".
  • lo que se está reproduciendo (la twig de trabajo) es "de ellos ".

Buena punta mnemotécnica de CommaToast :

lo que sea que HEAD señale es "nuestro"

(y lo primero que hace un git rebase upstream es realizar la git rebase upstream la twig upstream encima de la cual desea volver a establecer la base: HEAD se refiere a la cadena upstream : la ours ahora).


La confusión probablemente proviene del rol de la twig de trabajo en una git merge clásica.
Cuando te estás fusionando:

  • la "twig de trabajo" es la que contiene lo que está "hasta ahora fusionada", y se considera como "nuestro",
  • mientras que el otro compromiso representa lo que está siendo reproducido, pero no se reproduce, en la parte superior de la twig de trabajo, y considerado como "su".

Como menciona la página de git rebase , una combinación durante una rebase significa que el lado se intercambia.


Otra forma de decir lo mismo es considerar que:

  • lo que tenemos en la twig de salida es ' nuestro ',
  • lo que teníamos (y está siendo fusionado o repetido) es ' suyo '.

En una fusión :

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

, no cambiamos la twig actual 'B', entonces lo que tenemos es aún en lo que estábamos trabajando (y nos fusionamos de otra twig)

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

¡Pero en una rebase , cambiamos de lado porque lo primero que hace una rebase es verificar la twig ascendente! (para reproducir los commits actuales en la parte superior)

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

Un git rebase upstream cambiará primero HEAD of B a HEAD de la twig upstream (de ahí el cambio de 'ours' y 'theirs' en comparación con la twig de trabajo "actual" anterior).

 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 

, y luego la rebase reproducirá 'sus' confirmaciones en la nueva 'nuestra' 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 

El único paso adicional con git svn rebase es que git svn rebase se realiza una "búsqueda" de svn en la twig remota de Git que representa las confirmaciones de SVN.
Tienes inicialmente:

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

, primero actualiza la twig de seguimiento de SVN con nuevos commits provenientes de SVN

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

, luego cambia la twig actual al lado SVN (que se convierte en "nuestro")

 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") 

, antes de reproducir los commits en los que estabas trabajando (pero que ahora son "suyos" durante esa 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