Sistemas de Control de Versiones (Subversion y Mercurial)
En esta ocasión vamos a ver qué es un Sistema de Control de Versiones y cómo se utiliza.
Voy a dividir la entrada en 4 partes bien diferenciadas. Primero una breve introducción, explicando qué son y qué tipos hay. A continuación, una descripción del uso de VCS, seguida por una descripción de DVCS. Finalmente, una entrada avanzada de cómo utilizar DVCS. Si ya eres un usuario de DVCS, a lo mejor te interesa saltarte las dos primeras partes.
Introducción
Un Sistema de Control de Versiones (SCV o, en inglés, VCS o “Version Control System”) tiene una estructura similar a un sistema de archivos. La diferencia está en que se puede acceder a distintas versiones de los archivos y operar con estas versiones. Es decir: Es un sistema de ficheros con versionado.
Hay distintos tipos. Los más sencillos son los sistemas locales, útiles para un único usuario. En la era de la nube, no tiene sentido en pensar en sistemas de este tipo y ya no se mantiene ninguno de éstos. Hace tiempo trabajé con PVCS y era un verdadero infierno (una persona estaba encargada del PVCS y era la única que accedía al mismo). Los ignoraremos.
Un poco más complejos son los denominados VCS (“Version Control System”). Éstos diferencian entre el sistema central y la copia local (working copy).
Los más utilizados actualmente son los DVCS ("Distributed Version Control System"), en los que puede haber más de una copia remota y éstas se pueden sincronizar entre ellas.
Echémosle un vistazo rápido a todos ellos.
VCS
Aunque las empresas están abandonándolos, aún siguen siendo muy utilizados.
El sistema consiste, básicamente, en una copia local y un servidor remoto. Las modificaciones se realizan sobre la copia local y luego se envían al servidor. Cada máquina que tiene una copia local se sincroniza bajo demanda con el servidor remoto.
Subversion , CVS , … Han sido los más utilizados. Vamos a ver un poquito de Subversion:
- init: permite inicializar un repositorio.
- checkout: descarga un repositorio remoto en una carpeta local (working copy), desde la que podemos manipular los archivos.
- update: comprueba si hay actualizaciones en el servidor y se las descarga a la copia local. Si hay conflictos (hemos tocado un archivo que alguien ya ha modificado en el servidor), tratará de resolverlos. Si no puede, dejará los archivos marcados como “conflicto”.
- add: mientras que no hagamos add a un archivo, éste será ignorado.
- commit: crea una nueva versión, enviando al servidor las modificaciones desde la última vez que se utilizó esta orden.
- remove: el archivo deja de estar gestionado. Hay que tener en cuenta que las versiones que subimos con el archivo seguirán estando ahí, pero a partir de ese momento, las nuevas versiones no lo mostrarán.
- diff: permite ver las diferencias existentes entre las distintas versiones de un mismo fichero.
- log: muestra los cambios ocurridos en el repositorio.
El uso típico de este tipo de repositorios es:
- El administrador crea el repositorio (init) y publica la dirección en la que se encuentra (https, ssh, …).
- El usuario se descarga el repositorio a su copia local (checkout).
- El usuario comienza un ciclo de iteraciones sucesivas de las órdenes siguientes, aunque usará el resto de forma ocasional:
- Modificar el código
- Subir cambios (commit). En este punto se realiza un update automático y, si hay conflictos, se exige su resolución antes de permitir el commit.
Los sistemas de este tipo tienen un problema: si no hay conexión, no se puede hacer nada con el repositorio, ya que la mayor parte de la lógica está en el servidor.
DVCS
En este caso entra en juego un componente más: un servidor local. Este servidor local puede ser una copia local del servidor remoto. Esta característica permite trabajar con el servidor aunque no exista conexión a la red. Cuando se desee, se puede sincronizar el servidor local con el servidor remoto.
La manera de trabajar con el servidor local es muy similar a la utilizada por los VCS, aunque pueden cambiar los nombres de las órdenes. Por ejemplo, la orden “clone” de Mercurial equivaldría al “checkout” de subversion.
Evidentemente, hay una serie de instrucciones adicionales que nos permiten trabajar con el servidor remoto. Dado que esto no es un tutorial de mercurial, obviaré estas órdenes comunes y me centraré en las nuevas operaciones:
- pull: permite traerse los cambios del repositorio remoto al repositorio local.
- push: Envía los cambios del repositorio local (ojo, no la copia de trabajo) al repositorio remoto.
- branch: Permite crear ramas nuevas. De esto hablaremos en el siguiente punto.
- branches: Muestra la lista de ramas existentes.
- merge: Mezcla dos colas.
- out: Muestra la lista de changesets (commits) que están en el servidor local pero no en el servidor remoto.
No hay un ciclo habitual con los DVCS. Sin embargo, podríamos poner como “ciclo sencillo” la intercalación entre:
- pull
- Ciclos de tipo VCS
- push
Algunos ejemplos de DVCS son Mercurial , Git , Bazaar , Veracity o Plastic SCM .
DVCS Avanzado
Vamos a ver aquí tres niveles. El primero se tratará del manejo de ramas (“branches”); el segundo, de hooks y el tercer, del manejo de repositorios remotos.
Branches
El manejo de ramas permite realizar un trabajo paralelo sin afectar a la rama principal. Las ramas principales suelen llamarse algo como “trunk”, “default”, … y suelen ser las más importantes.
Existe una corriente que defiende el “Un cambio, una rama”, de manera que antes de comenzar a hacer cambios, debes crearte una rama y, posteriormente, mezclar con la rama principal. Este planteamiento permite pasar varios días trabajando en la rama sin afectar al trabajo de los demás. No es necesario esperar al último momento para aplicar todos los cambios, ya que se puede mezclar una rama con la rama principal en cualquier momento, facilitando así el poder actualizarse o reduciendo los posibles conflictos.
Existe también la posibilidad de crear ramas de ramas o de mezclarlas entre ellas, complicando así el grafo generado.
Hay que tener en cuenta que, durante la mezcla de código, es posible que el algoritmo de mezclado falle, así que es buena idea combinar estas técnicas con robustas baterías de pruebas.
Hooks
Los repositorios pueden lanzar acciones automáticas cuando se producen ciertos eventos. Por ejemplo, podrían enviarnos un e-mail cuando una rama se mezcla con la rama principal, o comprobar que el código cumple ciertos criterios de calidad.
Este tipo de técnicas pueden ser muy provechosas, aunque puede requerir tanto mantenimiento como para dedicar parte del personal a manejarlas.
Múltiples repositorios
Finalmente, llegamos a los múltiples repositorios. Existe la opción de tener repositorios remotos réplica. Esto significa que podemos sincronizar nuestros cambios contra una de estas réplicas y ésta se sincronizará tarde o temprano con otra de las réplicas.
La sincronización entre repositorios puede ser manual o automática, y puede dar lugar a un flujo de trabajo distinto según se necesite. Por ejemplo, puede utilizarse esta técnica para mantener repositorios remotos, de manera que se incremente la velocidad entre los working copies y el servidor central o, lo que puede resultar más provechoso, definir unas calidades para cada uno de los repositorios.
Veamos un ejemplo… Podemos tener el repositorio de uso habitual, donde “cabe todo”, llamándole “Development”; otro repositorio del que se realizan pruebas unitarias automáticas, llamado “testing”; si las pruebas automáticas pasan, podríamos tener otro con las pruebas de integración “integration”; si estas pasan, otro con las pruebas de calidad “QA” y, si estas pasan, otro con el código definitivo “Release”. Cuando hay una nueva rama en este repositorio, podríamos sincronizarlo con “Development” y, así, cerramos el círculo.
No he leído nada aún al respecto, pero supongo que a esto es a lo que hace referencia la “Integración contínua”.
Con el fin de no hacer crecer disparatadamente todos los repositorios, se pueden mezclar sólo ciertas ramas de un repositorio a otro, simplificando las mezclas y reduciendo la historia.
Conclusión
El uso de todas las técnicas avanzadas puede provocar flujos de trabajo muy diferentes, pero todos ellos útiles para el desarrollo de software. Cualquier empresa de más de 5 desarrolladores que trate de hacer software sin utilizar un VCS o un DVCS está destinada al fracaso; no podrá obtener una calidad competitiva ni unos plazos aceptables.
Más información
Hoy día es raro no haber oído hablar de los sistemas de control de versiones. De todas maneras, os recomiendo apuntaros al blog de mis amigos de `Codice Software] donde, entre muchas cosas interesantes, explican más a fondo un flujo de trabajo con su propia herramienta.
En breve voy a comenzar la lectura de un libro que promete ser interesante, Version Control by Example, propuesto por Eric Sink, que os podéis descargar gratuítamente o, si tenéis suerte como yo, conseguirlo de forma gratuita en papel .
También os propongo echar un ojo a la Wikipedia .
Y, por si fuera poco, existe la posibilidad de utilizar algunos de ellos de forma remota, utilizando Github , Bitbucket , Launchpad , Savannah , Gna! , … Para gustos, los -colores- sistemas de control de versiones :D