Node:Fusiones múltiples, Next:, Previous:Fusión de cambios desde las ramas al tronco, Up:Ramas



Fusiones múltiples

A veces, una rama seguirá teniendo un desarrollo activo aún después de que su contenido haya sido fusionado con el tronco. Por ejemplo, esto puede suceder si se descubre un segundo fallo en la antigua distribución pública y este fallo ha de ser corregido en la rama. Cabe la posibilidad de que alguien no hubiese entendido la broma que hay en random.c, así que tendría usted que añadir una línea explicándola:

floss$ pwd
/home/loquesea/miproyecto_rama
floss$ cat b-subdir/random.c
/* Imprimir un número aleatorio. */
#include <stdio.h>
void main ()
{
  printf ("Un número aleatorio.\n");
  printf ("¿Ha entendido el chiste?\n");
}
floss$

y enviar el cambio. Si también es necesario fusionar esa corrección en el tronco, podría tener la tentación de utilizar el mismo comando "update" de antes en la copia de trabajo presente en el tronco para llevar a cabo la "re-fusión":

floss$ cvs -q update -d -j Release-1999_05_01-bugfixes
RCS file: /usr/local/cvs/miproyecto/hello.c,v
retrieving revision 1.5
retrieving revision 1.5.2.1
Merging differences between 1.5 and 1.5.2.1 into hello.c
RCS file: /usr/local/cvs/miproyecto/b-subdir/random.c,v
retrieving revision 1.2
retrieving revision 1.2.2.2
Merging differences between 1.2 and 1.2.2.2 into random.c
rcsmerge: warning: conflicts during merge
floss$

Como puede ver, este comando no ha tenido el efecto deseado: nos encontramos con un conflicto, a pesar de que la copia en el tronco no había sido modificada y, por tanto, no esperábamos encontrarnos ninguno.

El problema reside en que el comando "update" se ha comportado exactamente de la forma descrita: ha intentado tomar todos los cambios habidos desde la raíz de la rama y su extremo final, y a continuación fusionarlos tomando como referencia la copia de trabajo actual. El único problema está en que algunos de estos cambios ya habían sido fusionados desde esta copia de trabajo, de ahí que surgiese el conflicto:

floss$ pwd
/home/loquesea/miproyecto
floss$ cat b-subdir/random.c
/* Imprimir un número aleatorio. */
#include <stdio.h
void main ()
{
<<<<<<< random.c
  printf ("Un número aleatorio.\n");
=======
  printf ("Un número aleatorio.\n");
  printf ("¿Ha entendido el chiste?\n");
>>>>>>> 1.2.2.2
}
floss$

Llegados a este punto, podría intentar resolver estos conflictos a mano, dado que no es difícil ver lo que es necesario hacer en cada fichero. Sin embargo, es todavía mejor tomar medidas desde el principio para evitar conflictos. Pasando dos opciones "-j" en lugar de una, obtendrá sólo los cambios habidos desde la última vez que hizo una fusión con el extremo final de la rama, en lugar de tener en consideración todos los cambios habidos en ella. La primera -j le da el punto inicial de la rama, y la la segunda es sólo el nombre de la rama, que implica su extremo final y más reciente.

La cuestión entonces es, ¿cómo puede especificar el punto de la rama desde el que quizo la última fusión? Una forma de hacerlo sería indicar una fecha junto con el nombre de la marca dispuesta en la rama. CVS ofrece para ello una sintaxis especial:

floss$ cvs -q update -d -j "Release-1999_05_01-bugfixes:2 days ago" \
                     -j Release-1999_05_01-bugfixes
RCS file: /usr/local/cvs/miproyecto/b-subdir/random.c,v
retrieving revision 1.2.2.1
retrieving revision 1.2.2.2
Merging differences between 1.2.2.1 and 1.2.2.2 into random.c
floss$

Si el nombre de la rama va seguido de un signo de dos puntos y a continuación por una fecha en un formato válido para CVS, CVS incluirá solamente los cambios habidos después de esa fecha. De este modo, si sabe que la corrección original del fallo se envió a la rama hace tres días, el comando precedente fusionaría solamente la segunda corrección.

Una forma mejor de hacer esto, en este caso adelantándonos para tener en cuenta este tipo de eventualidades, sería marcar la rama después de implantar cada corrección (sólo una marca normal; no se trata de iniciar una nueva rama ni nada parecido). Supongamos que después de corregir el fallo en la rama y aplicar la corrección al repositorio, hacemos esto en la copia de trabajo de la rama:

floss$ cvs -q tag Release-1999_05_01-bugfixes-correc1
T README.txt
T hello.c
T a-subdir/loquesea.c
T a-subdir/subsubdir/fish.c
T b-subdir/random.c
floss$

De esa forma, cuando llegue el momento de fusionar el segundo cambio en el tronco, podrá utilizar la marca que ha tenido la buena idea de colocar ahí para delimitar la revisión anterior:

floss$ cvs -q update -d -j Release-1999_05_01-bugfixes-correc1 \
                     -j Release-1999_05_01-bugfixes
RCS file: /usr/local/cvs/miproyecto/b-subdir/random.c,v
retrieving revision 1.2.2.1
retrieving revision 1.2.2.2
Merging differences between 1.2.2.1 and 1.2.2.2 into random.c
floss$

Ni que decir tiene que este método es mucho mejor que intentar recordar cuánto tiempo hace que hizo tal o cual modificación, pero sólo funcionará si se acuerda de marcar la rama cada vez que la fusione con el tronco. La lección aprendida aquí es, por tanto, ¡marcar pronto y a menudo! Es mejor pecar de tener demasiadas marcas (siempre y cuando tengan nombres lo suficientemente descriptivos) que de tener muy pocas. En estos últimos ejemplos que le he dado no había ninguna necesidad de que la nueva marca de la rama tuviese un nombre similar al de la marca de la rama en sí. Si bien yo utilicé el nombre Release-1999_05_01-bugfixes-correc1, también podría haber sido correc1; sin embargo, es preferible emplear el primero, dado que contiene el nombre de la rama y por tanto no existirá la posibilidad de que sea confundido con la marca de alguna otra rama. (Recuerde que los nombres de las marcas son únicos dentro de los ficheros, no dentro de las ramas. No puede tener dos marcas llamadas correc1 en el mismo fichero, aunque se refieran a revisiones que se encuentran en diferentes ramas.)