2010-06-02 9 views
84

Uso git-svn y noté que cuando tengo que arreglar un conflicto de fusión después de realizar un git svn rebase, el significado de las opciones --ours y a por ejemplo git checkout está invertido. Es decir, si hay un conflicto y deseo conservar la versión que proviene del servidor SVN y desechar los cambios que realicé localmente, debo usar ours, cuando esperaría que fuera theirs.¿Por qué se invierte el significado de "nuestro" y "de ellos" con git-svn

¿Por qué 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" 
+0

Jut actualicé mi respuesta con muchos diagramas para ilustrar mejor el lado "nuestro" y "el suyo". – VonC

+1

Ver también https://github.com/git/git/commit/f30301657b68561392d910f6196380dd3976549e – VonC

Respuesta

211

Eso parece coherente con lo que hace un rebase.

  • git svn rebase voluntad obtiene las revisiones de los padres SVN del actual jefe y rebasa la corriente (no comprometidos a SVN) trabajan en contra de ella.

  • git rebase menciona:
    Tenga en cuenta que un rebase de fusión funciona mediante la reproducción de cada confirmación de la rama de trabajo en la parte superior de la rama <upstream>.
    Debido a esto, cuando un conflicto de combinación que sucede: informó

    • el lado de la nuestra es la serie hasta el momento-porcentualizada, empezando por <upstream>,
    • y la suya es la rama de trabajo.
      En otras palabras, los lados se intercambian.

git rebase las repeticiones de cada confirmación de la rama de trabajo en la parte superior de la rama <upstream>.

Si reconcilia ambas definiciones:

  • las confirmaciones procedentes de SVN son los que están en la parte superior de los cuales se reproducen confirmaciones Git locales. Forman parte de la "serie rebasada hasta ahora", y se mencionan como "nuestro" (en su caso, el archivo test.txt con contenido bar)
  • la rama de trabajo (que contiene Git comete un error desconocido para SVN, en su caso, el archivo test.txt con contenido baz) es "suyo", y se están reproduciendo cada uno de esos commit locales de Git.

En otras palabras, SVN o no:

  • la "<upstream>" rama (en la parte superior de los cuales se reproduce nada, y que forma parte de las confirmaciones hasta ahora porcentualizada ") es" la nuestra ".
  • lo que se está reproduciendo (la rama de trabajo) es" theirs ".

Buena mnemonic tip por CommaToast:

apuntando lo de HEAD que es "nuestro"

(y la primera cosa que un git rebase upstream lo hace a la comprobación de la rama upstream En la parte superior de la cual desea volver a establecer la base: HEAD se refiere a upstream - ours ahora.)


La confusión es probable que venía del papel del poder trabajar en un clásico git merge.
Cuando está fusionando:

  • la "rama de trabajo" es la que contiene lo que está "hasta el momento se fusionó", y se considera como "nuestro",
  • mientras que el otro se comprometen representan lo que se está - - no se reproduce sino - se fusiona en la parte superior de la rama de trabajo, y se considera como "su".

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


Otra forma de decir lo mismo es tener en cuenta que:

  • lo que tenemos en la rama desprotegido es 'nuestro',
  • lo que teníamos (y se está fusionando o reproduciendo) es 'theirs'.

En una fusión:

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

, no cambiamos la rama actual 'B', así que lo que tenemos es todavía lo que estábamos trabajando en (y nos fusionamos de otra rama)

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

Pero en una base de datos, cambiamos de lado porque lo primero que hace una rebase es verificar la rama ascendente. (Para reproducir las confirmaciones de corriente en la parte superior de la misma)

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

Un git rebase upstream se cambie primero HEAD de B a la rama aguas arriba HEAD (de ahí el interruptor de 'nuestro' y 'ellos' en comparación con el anterior " actual "rama de trabajo.)

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 el rebase se volverá a reproducir 'su' se compromete en el nuevo 'nuestra' rama 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 un SVN "fetch" se realiza primero en la rama remota de Git que representa las confirmaciones de SVN.
Usted tiene un principio:

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

, actualizar primero la rama seguimiento SVN con nuevas confirmaciones procedentes de SVN

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

, a continuación, cambiar la rama actual a un lado SVN (que se convierte en "la nuestra ")

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 las confirmaciones que estaba trabajando (pero que ahora está 'de ellos' durante ese 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 
+9

Guau, ¡qué gran respuesta, gracias! Debo haber perdido completamente esa observación en la página de manual de '' git rebase' ... –

+9

+1 por una respuesta supremamente detallada –

+1

Esta respuesta debería haber sido enviada un par de cientos de veces más, pero supongo que no mucha gente usa git-svn . Gracias @VonC! – epologee

Cuestiones relacionadas