Apr 15

¿Qué debemos meter en el sistema de control de versiones?

 

Cuando trabajamos en proyectos que usan sistema de control de versiones, pero todavía no tenemos muy afianzado qué cosas debemos meter en dicho sistema, pueden aparecer determinados ficheros en los que nos entra la duda de si debemos meterlos o no. Por ejemplo, ¿metemos o no los ficheros de proyecto de eclipse o netbeans? ¿metemos o no las librerías externas a nuestro proyecto, como log4j, drivers de bd, etc?.  La decisión, por supuesto, depende mucho de los gustos personales de la gente que lleva el proyecto, pero también depende en parte de las herramientas que usemos que no tienen mucho que ver con el sistema de control de versiones. Voy a comentar aquí un posible criterio más o menos lógico.

En el sistema de control de versiones deben ir todos aquellos ficheros que nosotros debemos hacer o proporcionar manualmente al proyecto. No deben ir todos aquellos ficheros que se generan de forma automática.

En el primer grupo, los que nosotros generamos, están claramente los fuentes de nuestro código (los .java por ejemplo), los scripts de compilado o de arranque de la aplicación, los ficheros de configuración (properties de java), los iconos de nuestra aplicación, etc, etc. Quedarían excluidos, por ejemplo, los fuentes que genere automáticamente alguna herramienta o script a partir de otros ficheros que sí hacemos manualmente.

Es muy importante meter en el sistema de control de versiones absolutamente todo lo necesario para construir desde cero y ejecutar nuestra aplicación tal cual era en un momento dado. De nada sirve tener versiones de los fuentes si no tenemos también almacenadas las versiones correspondientes de los scripts de arranque, de los ficheros de configuración (properties) o de creación de las tablas de base de datos.

En el segundo grupo, los generados automáticamente y que no van en el sistema de control de versiones, están los ejecutables y librerías que genera nuestro proyecto. Ni siquiera tendríamos que meterlos para conservar una versión especialmente estable o buena, ya que los sistema de control de versiones suelen soportar cosas como etiquetas o ramas y bastaría con marcar los fichero que sí van con una etiqueta para ser capaces de generar ese ejecutable estupendo.

Bien, esos son los ficheros más o menos claros, pero, ¿qué hacemos con las librerías externas?. Esta decisión ya puede depender de gustos y de las herramientas que usemos. Si usamos, por ejemplo, maven, todos los desarrolladores tendrán acceso a esos jar a través de internet de forma automática y sin preocuparse en absoluto de ello, por lo que con este tipo de herramientas no es necesario en absoluto meter en el sistema de control de versiones cosas como log4j.jar, junit.jar o ojdbc14.jar. Si no usamos una herramienta de este tipo, para comodidad para los desarrolladores, debemos tener todos estas librerías accesibles de forma fácil en algún sitio y una buena opción es meterlas en el sistema de control de versiones. Normalmente metemos cada una de estas librerías una sola vez y no van a tener modificaciones. Un desarrollador nuevo tendrá todas las necesarias símplemente con hacer un checkout y los scripts de compilado sabrán dónde buscar estas librerías.

¿Y qué hacemos con los ficheros de proyecto del IDE de trabajo, como los .project, .classpath o .settings de eclipse?. Nuevamente, la decisión puede depender de gustos y de las herramientas a usar. Nuevamente, si usamos maven, el comando mvn eclipse:eclipse nos genera estos ficheros automáticamente, por lo que es cómodo generarlos para un desarrollador recién incorporado al grupo y no sería necesario meterlos en el sistema de control de versiones. Si no usamos este tipo de herramientas, podemos meter estos ficheros en el sistema de control de versiones, pero tenemos que ser muy conscientes de que pueden ser problemáticos:

  • A veces estos ficheros llevan paths absolutos, por lo que todos los desarrolladores deben sacar el proyecto en el mismo directorio absoluto en su ordenador (por ejemplo, C:\PROYECTO) y posiblemente, tener las librerías externas en el mismo path absoluto (sea dentro de control de versiones o no).
  • Si un desarrollador quiere modificar algo en su IDE que afecte a estos ficheros (por ejemplo, añadir una dependencia nueva para probar o símplemente, cambiar el nombre del proyecto porque no le gusta el oficial), debe ser muy cuidadoso para no hacer un commit de esos ficheros descuidadamente.

Si decidimos no meterlos, debemos ser conscientes de que los desarrolladores nuevos deben montar manualmente el proyecto. Y si decidimos hacer cambios "oficiales" (añadir una dependencia, por ejemplo), todos deben realizar ese cambio manualmente.

 

Nov 12

Más de Subversion

Hace poco me tocó hacer una rama CVS de los proyectos para estabilizar una versión para unas pruebas con el cliente. Ya se sabe, rama del repositorio del proyecto y rama de todos los repositorios con librerías que utilice el proyecto.

Pues bien, ha sido horrible. Son cuatro o cinco repositorios y cada uno de los proyectos/librerías a "enramar" tienen fácilmente tres mil ficheros java. Eché toda la tarde en hacer las dichosas ramas. Primero un update, luego el cvs tag para poner una etiqueta justo en el punto donde comienza la rama y luego el cvs tag -b para crear la rama. Al hacerlo CVS fichero a fichero, media hora larga con algunos de los repositorios mientras cvs hace el trabajo.

Se me ocurrió, harto de ello, montar un servidor de subversion, migrar alguno de los repositorios CVS a subversion (usando cvs2svn) y mirar a ver cuánto tarda subversion en hacer la rama (svn cp). Es casi inmediato, ya que realmente no realiza la copia real de todos los ficheros (lo hará cuando se vayan modificando si se van modificando) y tampoco tiene que andar recorriendo todos los ficheros para ver su versión actual (CVS tienen un número de versión para cada fichero, mientras que subversion tiene un único número para todo el repositorio).

Todo el mundo habla que los sistemas de control de versiones distribuidos, estilo Bazaar o Git son maravillosos. También se habla mejor de Subversion que de CVS, aunque no todos lo hacen. A mí realmente todo eso me parece bien, pero mientras no veo una necesidad real o una mejora importante, no veo tampoco necesidad de cambiar. Ahora sí he encontrado un motivo, así que es cuestión de empezar a mirar en serio la posibilidad de migrarlo todo a Subversion.

De momento descarto Bazaar o Git por tener menos soporte para los IDEs habituales (eclipse en concreto). Tampoco tengo muy claro lo veloz que puede ser hacer un branch de un repositorio grande si eso implica la copia completa de todo el repositorio, con su historia (ya digo, repositorios de tres mil clases java con cuatro o cinco años de historia y alrededor de veinte desarrolladores de media desarrollando día a día).

Jul 14

Jugando con Bazaar

Hace algunos meses descubrí Git y empecé a oir hablar de los sistemas de control de versiones distribuidos. Me quedé con las ganas de echarle un ojo con más calma y ver qué era exactamente eso, qué ventajas aporta y si merece la pena usarlo. Sin embargo, me echaba atrás el que Git sólo estuviera disponible para linux. Para windows había que usar cygwin o bien con cosas como msysgit.

Gracias a un comentario del post anterior, descubro Bazaar, con soporte para linux y windows, con una documentación bastante agradable y sobre todo, con fama de ser fácil de usar. Así que me puse a jugar con ello.

La instalación en Windows muy sencilla con el instalador. En Ubuntu con el gestor de paquetes synaptic también (eso sí, hay que buscar "bzr" que es el comando de línea de comandos para Bazaar (como cvs, o svn en CVS o Subversion).

Cogí uno de los proyectos que tengo en Java y cree el primer proyecto con Bazaar. Fue realmente sencillo, basta con situarse en el directorio del proyecto ya creado y ejecutar los comandos

$ cd /home/chuidiang/PROYECTO
$ bzr init
$ bzr add
$ bzr commit -m"Primera version"

Todo fue de perlas. Sin necesidad de instalar ningún servidor ni nada parecido ya tengo mi primer proyecto (ya existente previamente) bajo el control de versiones de Bazaar.

Me voy ahora a otro directorio y pruebo a "sacarlo". También es sencillo

$ cd /tmp
$ bzr branch /home/chuidiang/PROYECTO RAMA_PROYECTO

Y ya tengo mi copia de trabajo en /tmp.

Aquí empieza, además, la primera diferencia con un sistema de control de versiones normal. Si hubiese ejecutado el comando bzr checkout en vez de bzr branch, habría extraido en /tmp el proyecto de forma similar a CVS o SVN. Cualquier commit que hiciese, se haría directamente en /home/chuidiang/PROYECTO, como si fuese el servidor o repositorio central. Sin embargo, al hacerlo con bzr branch, tengo ahora en /tmp una copia completa e indpendiente del proyecto original en /home/chuidiang/PROYECTO. Puede hacer commits independientes en un lado y en otro, cada uno con su propia historia y sus propios comentarios.

Sin embargo, tenemos más comandos de Bazaar, como bzr push, bzr pull, bzr merge, etc que permiten tanto a uno como a otro, traerse los cambios hechos en el otro proyecto, o bien llevarse tus propios cambios al otro proyecto.

Con un sistema de control de versiones distribuido tenemos libertad de organizar los repositorios del proyecto como queramos. Podemos o no poner un repositorio central y los desarrolladores pueden llevar sus propias ramas, intercambiarse unos con otros los fuentes antes de llevarlos al repositorio central y cualquier combinación que se nos ocurra.

Por ejemplo, suele ser buena idea tener un repositorio central donde esté la última versión en condiciones del proyecto. Los desarrolladores, con bzr branch se hacen sus propias copias y repositorios locales. Tocan, prueban y hacen commits locales todas las veces que quieran, conservando toda la historia de sus ficheros. Cuando todo está en condiciones, llevan su copia local al repositorio central, donde se actualizará con toda la historia local del desarrollador.

Es más, dos desarrolladores trabajando en una funcionalidad común, pueden actualizarse sus repositorios locales de uno a otro todas las veces que haga falta. Cuando sus copias locales estén en condiciones, las pueden subir al repositorio central. Se evita así, que estos desarrolladores tengan que compartir código todavía no probado subiéndolo previamente al repositorio central.

En fin, una pequeña maravilla, abierta a tantas posiblidades como seamos capaces de imaginar.