2012-06-25 18 views
8

Al explorar la funcionalidad en Subversion, intenté probar el caso de uso descrito en la subsección Deshacer cambios de la sección Fusión básica del capítulo Ramificación y fusión del svnbook. Estoy usando la versión 1.6.4, pero el texto para esa sección es el mismo en ambas versiones del libro.Conflicto al intentar el ejemplo Deshacer cambios en Subversion

En mi directorio de copia de trabajo, edito un archivo testcode.py, agrego una línea por edición y la confirmo después de cada edición. Después de varias entregas, el archivo de texto es el siguiente:

this is my first import to trunk. r1. 

this is my first commit, first edit of testcode.py. r2. 

this is another edit of testcode.py. r3. 

this is an edit of testcode.py. i'll get rid of this one. r4. 

this is another edit of testcode.py. keeping it. r5. 

yet another edit. keeping it. r6. 

Los números de revisión en el partido repositorio hasta las líneas en el archivo de manera que en /trunk/[email protected], la última línea del archivo es el que termina con rN. Lo que quiero hacer es eliminar la línea que termina en r4, manteniendo todo lo demás antes y después sin cambios.

Siguiendo el ejemplo de la sección Deshaciendo cambios del svnbook, funciono con el comando

svn merge -c -4 file:///path_to_repos/trunk 

Esto crea un conflicto (al ejecutar ese comando, no en comprometerse), por lo que el archivo de combinación izquierda contiene todo hasta la línea r4, y el archivo de fusión de derecha contiene todo hasta la línea r3. En otras palabras, en lugar de eliminar un cambio pasado, el comando parece querer revertir todo el archivo a la revisión 3 o 4, eliminando los cambios en las revisiones posteriores (5 y 6, en este caso).

La forma en que leo el ejemplo en el svnbook, que tiene el usuario revocando un cambio confirmado en la revisión 303 y confirmando el resultado a la revisión 350 sin conflictos, el comando que ejecuté debería haber producido un archivo con un estado svn de M que conserva todas las líneas excepto la que termina en r4.

¿Estoy leyendo incorrectamente el ejemplo del libro, es incorrecto el ejemplo, o hay alguna otra forma de error del usuario en el que me he caído por sorpresa?

+0

Definitivamente reproducible. Ahora necesito pensar por qué sucede. –

+0

Crear un parche con 'svn diff -c -4 foo.txt> foo.patch' y luego aplicarlo a' foo.txt @ HEAD' funciona como se esperaba - elimina la línea r4. –

+1

Por lo tanto, los parches funcionan, pero "un caso de uso extremadamente común para ** svn merge **", como lo dice el libro svn, es sencillo y tiene su propia subsección, simplemente no. Esto no inspira confianza en el comportamiento de la función de fusión de Subversion en procedimientos más complicados, como las ramas de reintegración. – krosbonz

Respuesta

4

El problema básico es que el algoritmo diff de Subversion maneja los cambios al principio y al final de los archivos de una manera que no es necesariamente intuitiva. Su ejemplo golpea ese caso de esquina, mientras que la mayoría de los cambios en el comodín no. Considere un archivo que tiene este aspecto después de una serie de confirmaciones:

later commit (r5) 
change to be reverted at beginning of file (r2) 
initial commit (r1) 
change to be reverted in middle of file (r3) 
initial commit (r1) 
change to be reverted at end of file (r4) 
later commit (r5) 

Tratando de revertir los commit en el principio o el final del archivo (revisiones 2 y 4 en el ejemplo), da un conflicto. Revertir el cambio al medio del archivo funciona como se esperaba.

Conceptualmente, podría ayudar pensar que los conjuntos de cambios tienen un alcance limitado por las líneas circundantes. Un cambio en el medio de un archivo está delimitado por las líneas circundantes sin cambios. El alcance de un cambio al principio o al final de un archivo se extiende hasta el comienzo o el final del archivo independientemente de qué tan lejos se mueva posteriormente ese punto.

Por lo tanto, en el ejemplo anterior, la segunda línea agregada en la revisión 5 viene justo en el medio del alcance de la revisión 4.De la misma manera que usted esperaría de un conflicto revertir la revisión 10 aquí porque los cambios en la revisión 11 están justo en el medio de ella:

...     <-- Line unchanged by revision 10, bounding its scope 
line from revision 10 <--\ 
line from revision 11  | Revision 10's scope 
line from revision 10 <--/ 
...     <-- Line unchanged by revision 10, bounding its scope 

que debe esperar un conflicto aquí, por la misma razón:

...     <-- Line unchanged by revision 10, bounding its scope 
line from revision 10 <--\ 
line from revision 11  | Revision 10's scope 
<EOF>     <--/ (No unchanged line bounding the scope this direction) 

Tenga en cuenta que esto solo pretende ser una explicación conceptual de por qué el principio y el final del archivo se tratan de forma diferente, no como una explicación exhaustiva para comprender el proceso de fusión de Subversion.

+0

Muy interesante y 100% reproducible. ¡Gracias! ¿Encontraste esto experimentando, escribiste el algoritmo diff, o está documentado en alguna parte? Podría pensar en poner una línea "ficticia" en mis archivos al principio y, especialmente, al final ahora. – scherand

+0

Esto es solo por experiencia. Realmente busqué documentación para incluir en esta respuesta, pero no pude encontrar nada. – blahdiblah

+0

Solo para asegurarme de que entiendo completamente, ¿puedo decir lo siguiente? La primera línea (más cercana a la parte superior) y la última (más cercana a la inferior) de un conjunto de cambios definen su "alcance". Si la primera línea del cambio es la primera línea del archivo (o la última, la última), el alcance se extenderá a la parte superior/inferior "para siempre". Y: si algo cambió * dentro del alcance * de ese cambio establecido en una confirmación posterior, el conjunto de cambios original no puede revertirse sin crear un conflicto. ¿Verdadero o falso? :) – scherand

Cuestiones relacionadas