Primeros pasos con Mercurial

Debería haber escrito este post hace algún tiempo pero ya se sabe como somos la gente importante que no tenemos tiempo a nada (modo ironic off). De todas formas nunca es tarde así que allá vamos, a adentrarnos en el maravilloso y fascinante mundo de Mercurial (hg para los amigos).

A estas alturas todos sabréis que Mercurial es una herramienta de sistema de control de versiones multiplataforma para desarrolladores de software implementado en Python (wikipedia dixit). Lo que igual se hace menos familiar es la facilidad con la que podemos crear un repositorio en 3 simples pasos:

Creando un repositorio

  • 1.-\"hg init\" para agregar control de versiones a la carpeta en la que estemos situados.
  • 2.-\"hg addremove\" para detectar todos los archivos nuevos y eliminados y agregar todo el contenido de la carpeta al repositorio, si queremos hacerlo poco a poco (directorio a directorio o archivo a archivo) podemos utilizar \"hg add directorio|archivo\".
  • 3.-\"hg commit\" para guardar los cambios actuales en el repositorio, seguro que os suena la frase \"hacer un commit\" ;).
Con esto tenemos lo básico, una carpeta de la que queramos hacer repositorio hg tan solo necesita esos 3 pasos. Además podemos adornarnos un poco:
  • \"hg serve\" arranca un servidor web ligero en http://localhost:8000/ donde podrás explorar el repositorio, ver las versiones antiguas del código… Si queremos lanzarlo en otro puerto \"hg serve -p 8001\".
  • \"rm -rf .hg\" dejar de usar control de versiones en esa carpeta, así de simple :P.

Sistema distribuido

El proceso de commit cambia un poco en concepto con respecto a otros sistemas de versiones centralizados como Subversion. Mercurial, al ser distribuido, tiene un repositorio propio en cada clonación de código. A ver si doy explicado esto porque tiene su miga.

Supongamos un repositorio remoto al que hacemos un \"hg clone\" para empezar a trabajar en local, en nuestra máquina. Desde ese mismo momento obtendremos -además de la clonación del código- el propio repositorio Mercurial en local de forma que los commits que hagamos se quedarán en nuestro repositorio hasta que hagamos un \"push\" al servidor:
  • \"hg push\" propaga los cambios locales al servidor remoto del repositorio.
  • \"hg update\" (ejecutado en el servidor remoto del repositorio) actualiza los cambios pendientes del anterior push.
Llegados a este punto ya tenemos el nuevo código en el repositorio servidor, de forma que si el propio repositorio es el virtualhost en producción los cambios serán inmediatamente efectivos. Si por el contrario producción es -a su vez- un clone del repositorio servidor faltaría este último paso:
  • \"hg pull\" para propagar los cambios que se hayan commiteado al servidor remoto en local.
  • \"hg update\" actualiza los cambios pendientes del anterior \"pull\".

Esquema

En resumen, tal y como he planteado la organización en cada proyecto tendremos un mínimo de tres repositorios: local_devel ? repositorio_servidor ? producción (obviamente si hay varios desarrolladores también habrá más repositorios locales o de desarrollo):
  • local_devel: Primero haremos un hg clone para obtener código y repo de repositorio_servidor, trabajamos en local haciendo nuestros commits y cuando tengamos lista una feature haremos un hg push a repositorio_servidor. Nunca olvidarse de hacer hg pull para actualizar los cambios de los demás antes de ponerse a trabajar (lo que en Subversion sería un update).
  • repositorio_servidor: Donde creamos el repositorio en un principio (hg init, adremove, y el primer commit), una vez creado se nutre del hg push de todos los desarrolladores que están trabajando en su local_devel y debería hacerse un hg update por cada hg push.
  • producción: Se supone que este repositorio debe ser el más estable así que solo admitirá operaciones hg pull seguidas de hg update cuando estemos seguros que los cambios del repositorio_servidor son estables y funcionales.

Notas

Nota: Los binarios que estén en producción y no agreguemos al repositorio no se borran/sobreescriben al hacer un pull, así que lo suyo sería agregar al repositorio -hablando de proyectos existentes- solo el código fuente, nada de binarios ni archivos que luego no se puedan sobreescribir en un pull. En otras palabras, se solucionan todos los problemas de sobreescritura -overwrite- que teníamos con Subversion, rsync y su --exclude.

Nota2: Veo que ha quedado un post demasiado técnico (palabras que no todo el mundo entiende) e igual algo criptográfico en cuanto al esquema (imagino que lo suyo hubiera sido hacer un gráfico), seguro que me he centrado en un caso bastante particular, pido perdón de antemano. Cualquier comentario, sugerencia o aclaración es bienvenida.
code

About the author

Óscar
has doubledaddy super powers, father of Hugo and Nico, husband of Marta, *nix user, Djangonaut and open source passionate.