Gestión básica de proyectos con Subversion
Lo que sigue a continuación son unos consejos sobre buenas prácticas para conseguir una gestión de proyectos eficaz utilizando Subversion. Las ideas no son (ni mucho menos) mías, posiblemente provengan de los desarrolladores originales de Subversion y posiblemente ellos llegaron a ellas desde prácticas para otros sistemas de control de versiones, pero son buenas y por eso merecen ser conocidas. Por supuesto no son exclusivas a Subversion, pueden utilizarse en otros sistemas de control de versiones con sólo modificar un par de comandos.
¿Empezamos?
Lo primero que se debe decidir cuando nos disponemos a realizar un proyecto utilizando Subversión como sistema de control de versiones es dónde y cómo se almacenarán nuestros archivos. Dependiendo de los recursos de los que dispongamos o de la importancia del proyecto podemos crear un nuevo repositorio para el proyecto o tener que utilizar un repositorio ya existente. Muchas veces los proyectos son lo bastante grandes para estar formados por subproyectos o quizá durante la vida del mismo se creen nuevos proyectos asociados a él, por lo que la recomendación es crear un directorio por cada subproyecto o proyecto asociado en la raíz del repositorio. Incluso si comenzamos un repositorio nuevo y sólo vamos a tener un proyecto en él, utilizar un directorio para el proyecto en la raíz es recomendable, ya que permite que posteriormente se añadan más proyectos al repositorio sin tener que mover el arbol antiguo (cosa que en Subversion es muy sencillo pero en otros sistemas de control de versiones no lo es tanto).
Sobre lo que no parece haber opiniones disidentes es sobre la estructura dentro de estos directorios de los proyectos (o dentro del raíz si optamos por tener sólo un proyecto por repositorio). Dentro de cada proyecto deben existir los siguientes directorios:
trunk(tronco): En este directorio se almacena todos los archivos y es donde trabajaran los desarrolladores día a día.branches(ramas): Este directorio almacena copias de los archivos del arbol principal sobre los que trabajaran grupos de desarrolladores para estabilizar un lanzamiento, corregir sus errores o realizar grandes experimentos que no se pueden realizar sobre el arbol principal.tags(etiquetas): Este directorio no es para que los desarrolladores trabajen sobre él, sino que se utiliza para realizar marcadores de estados determinados del arbol principal o de las ramas y que se pueda tener acceso fácil es ellos.
En muchos sitios se utiliza esta estructura básica de directorios almacenando todas las ramas y todas las etiquetas directamente en los directorios correspondientes, posiblemente por herencia de la incapacidad de algunos sistemas de control de versiones de crear jerarquias de ramas y etiquetas. Pero como Subversion nos lo permite podemos crear una jerarquia dentro de los directorios de branches y tags (el directorio trunk debe organizarse como si fuera la raíz del directorio del proyecto, un tema bastante amplio y fuera del ámbito de esta entrada).
releases(lanzamientos): Se utilizará para realizar un seguimiento a los lanzamientos de las diferentes versiones del producto.bugs(bichos): Se utilizará para la corrección de errores o fallos encontrados en las diferentes ramas.test(pruebas): Este directorio sólo existen dentro debranchesy lo utilizan los desarrolladores cuando se va a realizar un cambio a gran escala pero no se desea interferir con el desarrollo normal del proyecto en trunk.
Por supuesto si optamos no seguir esta estructura de directorios y seguimos la más clásica estructura plana es recomendable utilizar unos prefijos para distingir el cometido de cada rama o etiqueta: REL- para los lanzamientos, BUG- para los errores y TST- para las ramas de prueba son buenas elecciones.
Dentro de cada uno de los directorios las diferentes ramas y etiquetas deben tener nombres significativos: para los lanzamientos serían el número de la versión (los clásicos 1.0, 1.0.1, 2.0b1, etcétera) y para los bugs lo ideal es utilizar el número de identificación de nuestro sistema de gestión de bugs (porqué tendrás un sistema de gestión de bugs ¿no?). Las ramas de pruebas son más libres, pero un nombre corto y suficientemente descriptivo siempre es mejor.
Los desarrolladores normalmente trabajarán sobre el trunk realizando cambios y corrigiendo errores directamente en él. Cuando los jefes del proyecto decidan que el proyecto está preparado para un lanzamiento es el momento de crear una nueva rama de lanzamiento.
$ svn copy -m “Creando rama de lanzamiento 1.0″ svn://example.com/proyecto/trunk svn://example.com/proyecto/branches/release/1.0
Committed revision 500.
En este momento parte de los trabajadores se dedicarán a eliminar los fallos aún existentes en esta rama hasta que esta se encuentre libre de ellos (bueno, al menos hasta que los desarrolladores no puedan encontrar más). Para trabajar en esta rama los desarrolladores deben hacer un checkout del nuevo arbol (o realizar un switch, aunque es más sencillo lo primero).
$ svn co svn://example.com/proyecto/branches/releases/1.0 rel-1.0
[...]
Checked out revision 500.
Cuando los jefes de proyecto vean que la rama es lo suficiente madura para realizar un lanzamiento se deberá crear una etiqueta de lanzamiento.
$ svn copy -m “Creando etiqueta de lanzamiento 1.0.0″ svn://example.com/proyecto/branches/releases/1.0 svn://example.com/proyecto/tags/releases/1.0.0
Committed revision 501.
Los errores que se encuentren una vez que esta versión se haya lanzado deberán ser corregidos en la rama, no en la etiqueta. Las etiquetas deben ser estáticas y ningún desarrollador debe trabajar sobre ellas. Una vez que el número de errores sea considerable se seguirá el mismo proceso para crear una nueva etiqueta de la rama 1.0 creando la etiqueta 1.0.1. De igual forma cuando sea momento de una nueva gran versión se creará una nueva rama 1.1 (o puede que incluso 2.0) y de ella se crearán más etiquetas (1.1.0, 1.1.1, etcétera).
De esta forma los errores encontrados en cada una de las ramas pueden ser fácilmente arreglados (y si fuera necesario corregidos en otras ramas también, como veremos en breve) y crear nuevas versiones con ellos corregidos soportando varias versiones (para los usuarios que deben seguir utilizando versiones antiguas).
Los fallos y los errores pueden manejarse de dos formas dependiendo de su solución. Los fallos simples son aquellos que son fácilmente arreglados haciendo modificaciones a uno o dos archivos (es decir, su resolución se traduce en una única revisión nueva del repositorio) y se pueden realizar directamente en la rama donde se ha encontrado el bug. Simplemente debemos descargar una copia de trabajo de la rama a corregir, realizar los cambios y enviarlos.
Pero lo más posible es que al tener varias ramas de desarrollo el fallo se encuentre en más de una de ellas (hemos estado “copiando” código de un lado al otro, es normal que tengamos fallos repetidos) así que debemos corregirlo en todas ellas. Subversion nos facilita la corrección, pero desgraciadamente no nos facilita encontrar las ramas afectadas, que pueden ser las anteriores, las posteriores e incluso el trunk. Para corregir una rama utilizando los cambios realizados en otra rama lo más sencillo es realizar un merge.
Para realizar un merge de un fallo sencillo debemos acordarnos del número de revisión de la corrección (un consejo para acordarse de él es apuntarlo en sistema de gestión de bugs). Supongamos que hemos corregido un fallo en la rama 1.1 creando la revisión 512 y queremos corregir el mismo fallo en la rama 1.0. Lo primero sería obtener un copia de trabajo de la rama 1.0 actualizada y a continuación:
$:rel-1.0/ svn merge -r511:512 svn://example.com/proyecto/branches/releases/1.1
[...]
$:rel-1.0/ svn commit -m “Mezcla r512 (bug 123)”
[...]
Commited revision 513.
Para fallos más complejos (no se pueden realizar con una sola revisión o llevan más de unas horas) la solución es un poco distinta. Para seguir la corrección del bug se creará una rama nueva (en el directorio bugs) utilizando el identificador del sistema de seguimiento de bugs y de esta rama se creará una nueva etiqueta que marque su comienzo (el nombre puede ser start-456, pre-456, in-456, siendo 456 el número del bug). Los desarrolladores trabajarán entonces en la rama para corregir el error y cuando se haya corregido se etiquetará de nuevo la rama (con el nombre correspondiente: end-456, post-456 o out-456). Estas dos etiquetas podrán ser utilizadas para mezclar los cambios realizados en otras ramas.
$ svn copy -m “Creando rama de bug 456″ svn://example.com/proyecto/branches/releases/1.1 svn://example.com/proyecto/branches/bugs/456
Commited revision 524.
$ svn copy -m “Creando etiqueta de comienzo de bug 456″ svn://example.com/proyecto/branches/bugs/456 svn://example.com/proyecto/tags/bugs/start-456
Commited revision 525.
El desarrollador descarga la nueva rama y corrige el error creando varias revisiones.
$ svn copy -m “Creando etiqueta de final de bug 456″ svn://example.com/proyecto/branches/bugs/456 svn://example.com/proyecto/tags/bugs/end-456
Commited revision 542.
El bug también debe ser corregido en el trunk.
$:proyecto/ svn update
At revision 542.
$:proyecto/ svn merge svn://example.com/proyecto/tags/bugs/start-456 svn://example.com/proyecto/tags/bugs/end-456
[...]
$:proyecto/ svn commit -m “Mezcla para bug 456″
[...]
Commited revision 543.
El último tema que queda por tratar son las ramas de pruebas. Estas se crean cuando se desean realizar cambios muy drásticos al proyecto, pero no nos podemos permitir interrumpir el desarrollo normal, por lo que se crea una rama donde un equipo de desarrolladores pueda trabajar sin interferir pero sin perder las capacidades que ofrece el sistema de control de versiones. Los procesos son muy parecidos a los ya descritos: se copia el arbol deseado a una rama de pruebas, los desarrolladores se la descargan y trabajan sobre ella y si finalmente se decide utilizar la rama de pruebas se realiza la mezcla en la rama original.
Existen un par de recomendaciones sobre las ramas de pruebas: la primera es que las copias no cuestan casi nada en Subversion por lo que es recomendable copiar todo el arbol, no sólo la parte que se va a cambiar ya que asi se permite la descarga de un árbol completo del proyecto fácilmente. La segunda es la utilización del modificador --stop-on-copy del comando log de Subversion, que detiene el listado del registro cuando se encuentra que se ha realizado una copia del elemento. La última entrada del registro será la revisión inicial desde la cual realizar el merge.
Por último decir que el etiquetado de un arbol no debe ocurrir con todos los archivos en sus últimas revisiones, si disponemos de una copia de trabajo con archivos en diferentes revisiones podemos etiquetar el estado de nuestra copia de trabajo. De esta forma podemos crear etiquetas de lanzamiento especiales con fallos corregidos o con partes de las ramas de pruebas que no se incluyen en las versiones normales.
- Referencia del comando
svn checkout. - Referencia del comando
svn commit. - Referencia del comando
svn copy. - Referencia del comando
svn log. - Referencia del comando
svn merge. - Referencia del comando
svn switch. - Referencia del comando
svn update.


21 de Marzo de 2007 a las 05:29
muy bueno la entrada, muy ilustrativa y quisiera saber si existe alguna herramienta grafica com las q hay en windows para podeer haccer menos truamatico el uso de subversion, obia mente para ser usada en linux (suse10.1)
21 de Marzo de 2007 a las 10:22
En la página de enlaces de subversion hay referencias a algunos clientes gráficos, alguno de ellos multiplataforma.
26 de Agosto de 2008 a las 10:49
Muy buena la explicación.
Te acabo de enlazar:
http://elmanytas.is-a-geek.net/?q=node/64