<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>RVBurke &#187; mercurial</title>
	<atom:link href="http://blog.rvburke.com/category/mercurial/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.rvburke.com</link>
	<description>Arquitectura y técnica</description>
	<lastBuildDate>Mon, 10 May 2010 18:22:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Repository formats matter a lot in Mercurial</title>
		<link>http://blog.rvburke.com/2006/12/14/repository-formats-matter-a-lot-in-mercurial/</link>
		<comments>http://blog.rvburke.com/2006/12/14/repository-formats-matter-a-lot-in-mercurial/#comments</comments>
		<pubDate>Thu, 14 Dec 2006 16:00:48 +0000</pubDate>
		<dc:creator>pachi</dc:creator>
				<category><![CDATA[english]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[software-libre]]></category>

		<guid isPermaLink="false">http://blog.rvburke.com/2006/12/14/repository-formats-matter-a-lot-in-mercurial/</guid>
		<description><![CDATA[Keith Packard discusses why robust repository formats are important for any version control software. This is really an important point when evaluating the robustness of any version control system, as you want to avoid the corruption of all your data due to a disk failure and an unfortunate way to store the tracked information. One [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://keithp.com/blog/Repository_Formats_Matter.html">Keith Packard discusses</a> why robust repository formats are important for any version control software. This is really an important point when evaluating the robustness of any version control system, as you want to avoid the corruption of all your data due to a disk failure and an unfortunate way to store the tracked information.</p>
<p>One sad point, as he&#8217;s a person I certainly admire for his work on free software, is that, while praising the way <a href="http://git.or.cz/">git</a> faces that problem, he unfairly bashes <a href="http://selenic.com/mercurial">Mercurial</a> (besides other VCSs). The fact is that the comparison done is not correct. While the comparison used to measure store size is between packed git and standard Mercurial, the robustness of the repository format comparison uses the unpacked git and standard Mercurial.</p>
<p>I believe this is more of a handwaving issue than any real concern about how git or Mercurial are doing the job.<br />
<span id="more-114"></span></p>
<p>Mercurial uses a compact representation of data with separate revlog files for each tracked file, manifest and changelog, which are all append-only. Due to the append-only nature of those writes, the changes in each new revision don&#8217;t affect previous revisions. You are that way as safe as you can be in any other system with respect to writes and the space usage is very good.</p>
<p>To achieve similar space efficiency git needs to pack the repository data. This is done rewriting the repo, and the operation has to be done from time to time (repack).</p>
<p>IF the atomic append-only writes to the manifest and revlog files in Mercurial can be considered dangerous, then repacking is even more so, as it forces a rewrite of all the repo data, multiplying the chance of a failure. </p>
<p>So, if any corruption can happen on a faulty write it will hit git (unpacked) or Mercurial in the same way, but anytime you pack your repo in git you&#8217;re risking your data and the write fails you can corrupt its repository.</p>
<p>That said, one can meditate whether this unlikely situation of failure is of so high importance, as, in distributed systems, a lot of other repos will act as a full backup of the canonical repo. Furthermore, both use atomical operations and safety should be more than good enough.</p>
<p>A <a href="http://www.selenic.com/pipermail/mercurial/2006-November/011678.html">short reply</a> to Keith&#8217;s post has been written by Matt Mackal, <a href="http://selenic.com/mercurial">Mercurial</a>&#8216;s main author, and detailed information about the <a href="http://www.selenic.com/mercurial/wiki/index.cgi/Design">repository format and other design details for Mercurial</a> can be found on the project&#8217;s wiki.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rvburke.com/2006/12/14/repository-formats-matter-a-lot-in-mercurial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Control de Versiones con Mercurial (III) &#8211; Publicación de proyectos</title>
		<link>http://blog.rvburke.com/2006/09/11/control-de-versiones-con-mercurial-iii-publicacion-de-proyectos/</link>
		<comments>http://blog.rvburke.com/2006/09/11/control-de-versiones-con-mercurial-iii-publicacion-de-proyectos/#comments</comments>
		<pubDate>Mon, 11 Sep 2006 12:08:45 +0000</pubDate>
		<dc:creator>pachi</dc:creator>
				<category><![CDATA[castellano]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[software-libre]]></category>

		<guid isPermaLink="false">http://blog.rvburke.com/2006/09/11/control-de-versiones-con-mercurial-iii-publicacion-de-proyectos/</guid>
		<description><![CDATA[Introducción Esta tercera parte de la serie de artículos sobre el control de versiones en proyectos de software está enfocada a la configuración del acceso y publicación de repositorios de Mercurial usando servidores HTTP o SSH. El traspaso de información entre distintos desarrolladores dispersos en la red es uno de los casos de uso en [...]]]></description>
			<content:encoded><![CDATA[<h1>Introducción</h1>
<p>Esta tercera parte de la serie de artículos sobre el control de versiones en proyectos de software está enfocada a la configuración del acceso y publicación de repositorios de Mercurial usando servidores HTTP o SSH.</p>
<p>El traspaso de información entre distintos desarrolladores dispersos en la red es uno de los casos de uso en los que se aprecia con mayor claridad la potencia de los sistemas de control de versiones distribuidos.</p>
<p>En la <a href="http://blog.rvburke.com/2006/08/25/control-de-versiones-con-mercurial-i-conceptos-generales/">primera parte</a> se puede leer una introducción a los conceptos fundamentales utilizados en los sistemas de control de versiones y Mercurial, mientras que la <a href="http://blog.rvburke.com/2006/09/08/control-de-versiones-con-mercurial-ii-uso-de-mercurial/">segunda parte</a> entra de lleno en el uso de Mercurial para gestionar un proyecto de software.</p>
<p><span id="more-23"></span></p>
<h1>Publicación de repositorios</h1>
<p>Para el trabajo en grupos distribuidos resulta fundamental la publicación de los diversos repositorios de trabajo de un proyecto. Es posible usar un servidor (o varios) en los que se agregan los repositorios públicos y el uso de servidores web o que usen el protocolo SSH es una de las formas más sencillas de hacerlo.<br />
Una de las cuestiones que surgen al publicar uno o más repositorios es el de los permisos que tienen los distintos usuarios en cuanto a la lectura o modificación de los repositorios. Mercurial delega en el sistema operativo el control de los permisos sobre los repostorios, por lo que la forma más natural de organizarlos es mediante la separación de privilegios por usuario. En esa situación, el problema se convierte entonces en el de la autentificación de los usuarios entrantes.</p>
<p>En este artículo se explican todos estos conceptos y cómo proporcionar acceso universal de lectura a los repositorios mediante el protocolo HTTP, y acceso de lectura o lectura y escritura mediante el protocolo SSH, usando autentificación por clave pública.</p>
<h1>Acceso de serie con el protocolo HTTP</h1>
<p>HTTP es el protocolo de comunicación que usan los servidores de la web, y es uno de los mejor soportados tanto en los servicios de alojamiento como por la infraestructura de la red (proxies). Mercurial incluye de serie un servidor de repositorios que usa como protocolo de comunicación HTTP.</p>
<p>El servidor incluido por defecto en Mercurial es especialmente útil para compartir un repositorio a través de la red de forma rápida y sencilla, sin necesidad de instalar ningún software adicional. Para poner en marcha ese servicio, simplemente basta con utilizar el siguiente comando mientras nos situamos dentro del directorio de trabajo del repostorio que queremos compartir:</p>
<blockquote><p><code>$ hg serve</code></p></blockquote>
<p>Una vez arrancado el servidor, es posible acceder al repositorio exportado usando como URL la dirección desde la que se sirve. El servidor integrado usa también por defecto el puerto 8000, para evitar conflictos con un servidor web que se encuentre en la misma máquina, pero es posible modificar el puerto usado utilizando la opción <em>-p puerto</em>.</p>
<p>Si, en una red local, nuestra máquina tuviese la dirección IP 192.168.0.10, podríamos acceder desde cualquier máquina de la red al proyecto para, por ejemplo, clonarlo así:</p>
<blockquote><p><code>$ hg clone http://192.168.0.10:8000 copia-local</code></p></blockquote>
<h1>Integración con un servidor HTTP dedicado (Apache)</h1>
<p>Si se pretende dar acceso de forma continuada a un conjunto de repositorios es preferible el uso de un servidor web dedicado tal como Apache.<br />
La forma de integrar Mercurial con el servidor HTTP es a través de una aplicación CGI especializada que se distribuye con la aplicación principal.</p>
<p>A continuación se explica la configuración de esta modalidad para compartir repositorios utilizando un servidor Apache, basándose en la experiencia del autor en la configuración de este servicio en un servidor compartido en una máquina del proveedor Dreamhost.</p>
<h2>Cuenta dedicada</h2>
<p>Para limitar los riesgos de seguridad del uso de una aplicación CGI que realiza operaciones de lectura y escritura, es preferible configurar una cuenta de usuario dedicada, diferente a nuestra cuenta habitual. Con esta precaución, en el caso de que la aplicación CGI se viese comprometida por un fallo de seguridad, solamente los datos accesibles por el usuario de la cuenta (preferiblemente sólo los de los repositorios), podrían estar en peligro. La cuenta, por tanto, deberá tener los mínimos privilegios posibles.<br />
En el ejemplo que usaremos en este artículo, el usuario se llamará <strong>mercurial</strong>.<br />
(Puede ser necesario configurar correctamente la codificación de caracteres con LC_ALL)</p>
<h2>Aplicación CGI</h2>
<p>En este artículo situaremos la aplicación CGI en el subdirectorio <strong>~/repos</strong></p>
<p>El ejecutable CGI que debemos instalar en ese directorio es <strong>hgwebdir.cgi</strong>, que se encuentra en la distribución estándar de Mercurial. Este ejecutable es el encargado de realizar la compartición de los repositorios y presenta la interfaz web.</p>
<p>En el archivo cgi existen un par de elementos para personalizar algunas opciones, para el caso en que se quieran mostrar páginas con codificaciones distintas a las predefinidas para el usuario (variable HGENC) y cuando la ruta de instalación de python no sea la general del sistema.</p>
<p>Junto con ese archivo debemos crear un archivo de configuración <strong>hgweb.config</strong> que servirá para indicar los repositorios compartidos y realizar la traducción entre la URL recibida y el directorio en el servidor. El contenido es el siguiente:</p>
<blockquote><p><code>[collections]<br />
    ./repos = ./repos</code></p></blockquote>
<p>En nuestro ejemplo simplemente indicamos que la raíz de los directorios con repositorios se encuentra en el directorio de instalación, pero es posible indicar otras rutas, e incluso indicar rutas específicas por proyecto o por repositorio.<br />
En el lado izquierdo se pone la ruta conocida (o la que se puede omitir en la url).</p>
<h2>Control de acceso y reescritura de direcciones</h2>
<p>Para realizar el control de acceso, permitir la ejecución de archivos CGI en nuestro directorio y hacer las direcciones de acceso (URLs) más sencillas podemos utilizar los sistemas de configuración estándar de Apache. Bien una configuración global, bien utilizando una configuración por directorio mediante el archivo .htaccess. La primera opción es la más adecuada cuando se tiene acceso a poder modificar la configuración global del servidor, pero aquí explicaremos la última es la opción, puesto que suele estar disponible incluso en servidores de alojamiento compartido, y es sencillo extrapolar la configuración al caso anterior si fuese necesario.</p>
<p>El contenido del archivo <strong>~/repos/.htaccess</strong> es el siguiente:</p>
<blockquote><p><code>Options +ExecCGI<br />
AddDefaultCharset iso-8859-15<br />
RewriteEngine On<br />
#RewriteBase /<br />
RewriteRule ^$ hgwebdir.cgi  [L]<br />
RewriteCond %{REQUEST_URI} !^/hgwebdir.cgi<br />
RewriteRule (.*) /hgwebdir.cgi/$1 [PT]</code></p></blockquote>
<p>Esta configuración permite la ejecución de CGIs, reescribe la dirección añadiendo al final hgwebdir.cgi o añadiendo hgwebdir.cgi/directorio/nombre-archivo cuando se solicite un nombre de archivo y un directorio.<br />
De esa manera nuestra aplicación recibirá la ruta que se solicita.</p>
<h2>Host virtual</h2>
<p>Por comodidad, es conveniente crear un subdominio o host virtual en nuestro dominio principal que esté redirigido hacia la aplicación CGI en la cuenta dedicada. En nuestro ejemplo, la dirección <strong>hg.midominio.org</strong> podría dirigirnos hacia el directorio <strong>repos</strong> del usuario <strong>mercurial</strong>.</p>
<h2>Configuración de los repositorios compartidos</h2>
<p>Hemos configurado ya el directorio de instalación de la aplicación CGI y hemos decidido que será también el directorio base del árbol de repositorios.<br />
Para cada proyecto tendremos un subdirectorio que contenga los repositorios publicados para dicho proyecto, por ejemplo, para el proyecto &#8220;proyecto&#8221; y el repositorio &#8220;main&#8221; tendríamos la siguiente estructura en disco: <strong>~/repos/proyecto/main</strong></p>
<p>Para que los detalles que nos presenta la interfaz web (abriendo en un navegador <em>http://hg.midominio.org/</em>) sean más descriptivos, es recomendable añadir algunos datos en el archivo de configuración de cada repositorio. Este es el archivo <strong>~/repos/proyecto/main/.hg/hgrc</strong> y los datos relevantes son:</p>
<blockquote><p><code>[web]<br />
contact = Pepito Pérez
<pepito AT perez DOT org>
description = Proyecto - Repositorio principal<br />
name = Proyecto<br />
style = gitweb<br />
allow_archive = gz zip bz2<br />
#allow_push = pachi, coya, ramon</code></p></blockquote>
<p>El significado de los distintos campos es bastante obvio, precisando aclaración únicamente:<br />
<em>style</em>: inidica el estilo que se usará en la interfaz web<br />
<em>allow_archive</em>: permite indicar los tipos de archivo que se permiten descargar. Se puede limitar para evitar la sobrecarga del servidor, al exigir cierto trabajo de la CPU.<br />
<em>allow_push</em>: aquí está comentada esta opción, por lo que solamente se permite el acceso para lectura al repositorio publicado por HTTP. La opción allow_push permite incluir un conjunto de usuarios a los que se les permitiría la escritura mediante <strong>push</strong> al repositorio. La autentificación de los usuarios se podría hacer también mediante la configuración del archivo <strong>.htaccess</strong>.</p>
<p>En nuestra configuración, evitaremos el acceso mediante contraseñas y daremos acceso de escritura usando autentificación con clave pública, un método mucho más seguro.</p>
<h2>Acceso a través de HTTP desde los clientes</h2>
<p>Ahora que está configurado el servidor para proporcionar acceso a los repositorios usando el protocolo HTTP es posible realizar cualquier operación (autorizada) desde los clientes simplemente indicando la URL para el protocolo HTTP:</p>
<blockquote><p><code>$ hg clone http://hg.midominio.org/proyecto/main proyecto-main-local<br />
$ hg pull http://hg.midominio.org/proyecto/main</code></p></blockquote>
<p>Estas órdenes accederían al repositorio <em>~/repos/proyecto/main</em> del servidor. Hay que cuidar la introducción de la URL de forma correcta, puesto que, gracias a nuestras reglas de reescritura de direcciones no es necesario añadir el directorio <em>repos</em> en la URL.</p>
<h1>Acceso de lectura/escritura con clave pública por SSH</h1>
<h2>El protocolo SSH</h2>
<p>SSH es un protocolo de comunicación mucho más seguro que HTTP al incluir la encriptación de los datos, evitando que se puedan interceptar datos privados o sensibles, y, si se combina con la autentificación mediante clave pública se evita también el posible compromiso de las claves de acceso a las cuentas utilizadas.</p>
<p>Una de las ventajas del protocolo SSH es que la mayoría de servidores suelen tener soporte para su uso.</p>
<h2>Autentificación con clave pública</h2>
<p>A menudo se usa como forma de autentificación en servidores un par usuario/contraseña. En este modo de autentificación un usuario registrado en el sistema se identifica como tal y posteriormente envía su contraseña para asegurar que se trata del usuario legítimo. El problema de esta forma de autentificación es que el envío de la contraseña se produce a través de la red, con lo que una línea no segura puede llevar a comprometer la identidad del usuario.</p>
<p>Existen métodos más modernos de autentificación basados en el intercambio asimétrico de información. Son los llamados sistemas de clave pública. En estos sistemas se utiliza un par de claves, una llamada <strong>clave pública</strong> y que sirve para identificar la autenticidad y descifrar los mensajes cifrados usando la otra clave, la <strong>clave privada</strong>.</p>
<p>La clave pública se distribuye y almacena en los servidores que se desea que puedan identificar al poseedor de la clave privada, mientras que la clave privada siempre queda en posesión del usuario que se identifica.<br />
El mecanismo utilizado es el siguiente: una vez iniciada la transmisión, sel servidor solicitar al cliente que desea iniciar una transacción que encripte un mensaje único (de usar y tirar) haciendo uso de su clave privada; luego comprueba que es posible desencriptar el mensaje correctamente usando la clave pública almacenada, y, en ese caso, da acceso al usuario.</p>
<p>La ventaja de este sistema es que en ningún momento se produce un intercambio de contraseñas por la red, quedando la clave privada siempre a salvo de cualquier intento de controlar la comunicación. Es sumamente difícil (prácticamente imposible en un tiempo razonable) generar la clave privada a partir de la clave pública o de ésta y un mensaje conocido encriptado, con lo que el sistema es muy seguro.</p>
<h2>Instalación</h2>
<p>Para poder utilizar SSH como protocolo de comunicación es necesario, además de un servidor de SSH, la presencia de un cliente que realice las operaciones de comunicación. Uno de los clientes más fiables, que además es software libre, es OpenSSH, y suele estar instalado en cualquier sistema GNU/Linux o BSD. En sistemas Windows es preferible, por más práctico, usar el conjunto de aplicaciones &#8216;Putty&#8217; (<strong>putty.exe</strong> y <strong>plink.exe</strong>), que se puede obtener en <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/">http://www.chiark.greenend.org.uk/~sgtatham/putty/</a>.</p>
<h2>Generación de pares de claves para controlar el acceso</h2>
<p>Uno de los primeros pasos que debemos dar es la generación del par de claves pública y privada. Para ello utilizamos la herramienta ssh-keygen de la siguiente manera:</p>
<blockquote><p><code>$ ssh-keygen -t rsa -f hg-identity</code></p></blockquote>
<p>La aplicación ssh-keygen devuelve un par de claves <strong>hg-identity, hg-identity.pub</strong>, que son la clave privada y la clave privada, que usaremos en los clientes y el servidor.</p>
<h1>SSH: Configuración del servidor</h1>
<h2>Instalación de las claves públicas de los usuarios autorizados</h2>
<p>Cada usuario guarda una lista de las claves públicas a las que permite el acceso en el archivo <strong>~/.ssh/authorized_keys</strong>.<br />
Debemos añadir en nuestra cuenta dedicada en el servidor la lista de usuarios a los que permitiremos el acceso por SSH a los repositorios publicados.</p>
<p>En él se añade una línea por cada clave, y tiene un aspecto similar a este:</p>
<blockquote><p><code>ssh-rsa FACeilOTrm2UFa2RAAGTCIxAAAIExRCBsdwYyLFNzaCiShtyr9qp9KJGPRvJExtnuP3td6EApGyLwb0DU2UJfr9xJG+1LUwBwai7m0bqbxwe3CVBc7ysudePiBbg88ZXHw/77z0CQTFNReySVzzaXyjKWeRxGTu+cyoBjEQcUTltj+ncG78xQYcKHfwC5cX6MgU=4Sk3 pepito@perez.org<br />
ssh-rsa DAGTCIxhtyr9yLqaC3td2RasdwYxtAAABApiSnuPFE9KJGPGCNzARv6IEJexREilOTrm2UFpGy3CVBUwai7mDeey2UJfr9xJHw/bwBG+1LUjK77z0CQbg88ZXxwc7ySVzzaTF0bqbsudePiBXy0NRLwWGTu+cyoBjYcKHxSk3cEQgU=cUTltj+ncG78xQX6MfwC54eR paco@perez.org</code></p></blockquote>
<p>Vemos que cada línea empieza por el tipo de clave usado (en este caso, <strong>ssh-rsa</strong>), la clave codificada como cadena alfanumérica, y acaba con un identificador arbitrario (como <em>pepito@perez.org</em>).</p>
<h2>Restricción de las operaciones al trabajo con Mercurial</h2>
<p>Es posible limitar la capacidad de los usuarios para que únicamente puedan realizar algunas operaciones con Mercurial . Esto facilita la publicacion de repositorios dando acceso a grupos de usuarios no totalmente confiables, sin comprometer la seguridad del sistema.</p>
<p>Para ello, podemos aprovechar la posibilidad de ejecutar una orden cada vez que se usa una clave pública para la autentificación. Esto se consigue insertando la opción <strong>command</strong> al principio de cada linea con una clave pública en el archivo <strong>~/.ssh/authorized_keys</strong>. Lo que haremos en nuestro caso es utilizar un script que filtrará y redirigirá las acciones permitidas al ejecutable de Mercurial.</p>
<p>El script <strong>hg-ssh</strong> es el que realiza este trabajo, está escrito por Thomas Arendsen Hein y se puede obtener en la distribución estándar de Mercurial, en el directorio <em>contrib</em>. Para simplificar el uso optamos por instalar el script en <strong>~/hg-ssh</strong>.<br />
El script usa como parámetros las rutas de los repositorios en los que se permite actuar y dejaría las entradas en el archivo <strong>~/.ssh/authorized_keys</strong> así:</p>
<blockquote><p><code>command="hg-ssh repo-pepito/ /repos/main ~/crew-repo", ssh-rsa FACeilOTrm2UFa2RAAGTCIxAAAIExRCBsdwYyLFNzaCiShtyr9qp9KJGPRvJExtnuP3td6EApGyLwb0DU2UJfr9xJG+1LUwBwai7m0bqbxwe3CVBc7ysudePiBbg88ZXHw/77z0CQTFNReySVzzaXyjKWeRxGTu+cyoBjEQcUTltj+ncG78xQYcKHfwC5cX6MgU=4Sk3 pepito@perez.org<br />
command="hg-ssh repo-paco/ /repos/main ~/crew-repo", ssh-rsa DAGTCIxhtyr9yLqaC3td2RasdwYxtAAABApiSnuPFE9KJGPGCNzARv6IEJexREilOTrm2UFpGy3CVBUwai7mDeey2UJfr9xJHw/bwBG+1LUjK77z0CQbg88ZXxwc7ySVzzaTF0bqbsudePiBXy0NRLwWGTu+cyoBjYcKHxSk3cEQgU=cUTltj+ncG78xQX6MfwC54eR paco@perez.org</code></p></blockquote>
<p>Vemos que es posible utilizar rutas absolutas, relativas, o con expansión del directorio de usuario a la hora de indicar la situación de los repositorios accesibles para cada usuario.</p>
<p>Con esto está ya completa la configuración por el lado del servidor. Ya está configurado el acceso para lectura y la interfaz web, están registrados los usuarios que pueden utilizar los repositorios a través de SSH y configurado el acceso para permitir únicamente operaciones en los repositorios autorizados para cada usuario.</p>
<h1>SSH: Configuración de los clientes</h1>
<p>Ahora veremos la parte de los clientes, que deben acceder a los repositorios remotos que acabamos de configurar.<br />
Como primer paso debemos indicar a nuestro cliente SSH el lugar donde guardamos nuestra clave privada para que nos identifique correctamente ante el servidor que hemos configurado. La configuración puede variar algo según la realicemos en sistemas GNU/Linux o BSD, o en sistemas Windows. Los primeros admiten cualquiera de las dos formas de configuración, aunque parece más limpia la primera que se indica.</p>
<h2>Sistemas GNU/Linux y BSD (o windows con MSYS)</h2>
<p>En sistemas GNU/Linux o BSD podemos configurar el usuario y la clave privada para el acceso por SSH a cada dominio. Esta configuración se lleva a cabo en el archivo <strong>~/.ssh/config</strong>:</p>
<blockquote><p><code>Host hg.midominio.org<br />
&nbsp;&nbsp;&nbsp;&nbsp;user hguser<br />
&nbsp;&nbsp;&nbsp;&nbsp;IdentityFile ~/.ssh/hguser-identity</code></p></blockquote>
<p>El <strong>Host</strong> <em>hg.midominio.org</em> identifica el dominio para el que son de aplicación las siguientes opciones. El <em>usuario por defecto</em> se indica tras la opción <strong>user</strong>, y la <em>clave privada</em> del archivo indicado tras la opción <strong>IdentityFile</strong>.</p>
<h2>Win32</h2>
<p>En sistemas Windows (en GNU/Linux se podría hacer igual) no es posible usar la configuración global anterior y por ello se debe recurrir a modificar la configuración de Mercurial. El archivo de configuración para cada usuario, <strong>Mercurial.ini</strong> (~/.hgrc en sistemas *nix), permite indicar la orden que se ejecuta para realizar la conexión por SSH:</p>
<blockquote><p><code>[ui]<br />
ssh=/path/a/plink.exe -ssh -i "c:\ruta\a\hg-identity" -l mercurial</code></p></blockquote>
<p>En este ejemplo se usa plink.exe, que es el cliente de SSH para Windows (ssh en *nix), y como opciones se indica <em>-ssh</em> para que use el protocolo ssh en la conexión, <em>-i &#8220;/ruta/a/hg-identity&#8221;</em> para indicar la ruta del la clave privada para identificarnos en la conexión, y <em>-l mercurial</em> para acceder al servidor a través del usuario <em>mercurial</em> (el usuario de nuestra cuenta dedicada).</p>
<h2>Primera conexión</h2>
<p>En ambos sistemas, para terminar de realizar la configuración, es necesario conectarse manualmente por primera vez a la máquina remota para que su clave pública sea añadida a las claves públicas reconocidas por nuestra máquina (también podemos haberla añadido manualmente con anterioridad). Esto se realiza con la siguiente orden:</p>
<blockquote><p><code>$ ssh hg.midominio.org -i ruta/a/hguser-identity -l mercurial</code></p></blockquote>
<p>o</p>
<blockquote><p><code>> plink.exe -ssh -i "/ruta/a/hg-identity" -l mercurial</code></p></blockquote>
<h2>Trabajo con los repositorios</h2>
<p>Para clonar un repositorio existente o traer cambios simplemente usamos las órdenes habituales de mercurial, indicando en la URL que el protocolo de comunicación es SSH:</p>
<blockquote><p><code>$ hg clone ssh://hg.midominio.org/repos/proyecto/main proyecto-main-local<br />
$ hg pull ssg://hg.midominio.org/repos/proyecto/main</code></p></blockquote>
<p>Hay que resaltar que, en este caso, y a diferencia del acceso con HTTP, es preciso indicar la ruta completa a los repositorios (incluyendo <strong>repos</strong>) desde el directorio raíz del usuario dedicado de nuestro servidor, puesto que es ahí donde se inicia el acceso por SSH.</p>
<blockquote class="nota"><p><strong>NOTA:<br />
    Si hay conflictos de usuario y no se envía correctamente el nombre de éste puede ser necesario añadir el usuario antes de la máquina:</strong></p>
<p><code>$ hg clone ssh://mercurial@hg.midominio.org/repos/proyecto/main proyecto-main-local<br />
        hg pull ssh://mercurial@hg.midominio.org/repos/proyecto/main</code>
</p></blockquote>
<p><del datetime="2006-09-11T11:45:57+00:00">Pendiente: Cambiar &#8220;repos&#8221; por &#8220;mercurial&#8221; e igualar la sintaxis del acceso por HTTP y SSH (Modificando RewriteRule o hgweb.config)</del></p>
<blockquote class="nota"><p><strong>NOTA:<br />
    En pascaline usamos los siguientes repositorios:</strong></p>
<p><code>$ hg clone ssh://hg.rvburke.com/repos/pascaline/main pascaline-main<br />
        hg clone ssh://hg.rvburke.com/repos/pascaline/pachi pascaline-pachi<br />
        hg clone ssh://hg.rvburke.com/repos/pascaline/pascaline-crew pascaline-crew<br />
        hg clone ssh://hg.rvburke.com/repos/pascaline/ramon pascaline-ramon<br />
        hg clone ssh://hg.rvburke.com/repos/pascaline/coya pascaline-coya</code>
</p></blockquote>
<h2>Enlaces interesantes</h2>
<p>Página con trucos sobre la <a href="http://grml.org/mercurial/">instalación y uso de Mercurial</a> y MQ.</p>
<div class="copyright">(c) Rafael Villar Burke 2006<br />
Se permite la copia, distribución y modificación de este texto siempre que se conserve el copyright y esta nota.</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.rvburke.com/2006/09/11/control-de-versiones-con-mercurial-iii-publicacion-de-proyectos/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Control de Versiones con Mercurial (II) &#8211; Uso de Mercurial</title>
		<link>http://blog.rvburke.com/2006/09/08/control-de-versiones-con-mercurial-ii-uso-de-mercurial/</link>
		<comments>http://blog.rvburke.com/2006/09/08/control-de-versiones-con-mercurial-ii-uso-de-mercurial/#comments</comments>
		<pubDate>Fri, 08 Sep 2006 01:09:20 +0000</pubDate>
		<dc:creator>pachi</dc:creator>
				<category><![CDATA[castellano]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[software-libre]]></category>

		<guid isPermaLink="false">http://blog.rvburke.com/2006/09/08/control-de-versiones-con-mercurial-ii-uso-de-mercurial/</guid>
		<description><![CDATA[Introducción Esta es la segunda parte de una serie de artículos introductorios al uso de sistemas de control de versiones. En la primera parte se explican los conceptos generales necesarios para comprender el funcionamiento y la forma de trabajo de un sistema de control de versiones. En esta segunda parte se explica el uso particular [...]]]></description>
			<content:encoded><![CDATA[<h1>Introducción</h1>
<p>Esta es la segunda parte de una serie de artículos introductorios al uso de sistemas de control de versiones.<br />
En la <a href="http://blog.rvburke.com/2006/08/25/control-de-versiones-con-mercurial-i-conceptos-generales/">primera parte</a> se explican los conceptos generales necesarios para comprender el funcionamiento y la forma de trabajo de un sistema de control de versiones. En esta segunda parte se explica el uso particular de Mercurial, de forma que sea posible realizar con esta herramienta la gestión del código de un proyecto de software.</p>
<p><span id="more-22"></span></p>
<h1>Mercurial</h1>
<p>Mercurial es una aplicación para el control de versiones publicada bajo una licencia libre (GPL). Sus principales características son el carácter distribuido y la gran velocidad de funcionamiento.</p>
<p>La página principal del <a href="http://www.selenic.com/mercurial/wiki/index.cgi">proyecto</a> contiene abundante información (en inglés) sobre su uso, trucos, además de versiones del programa para su instalación.</p>
<h1>Instalación de Mercurial</h1>
<p>Existen <a href="http://www.selenic.com/mercurial/wiki/index.cgi/BinaryPackages">paquetes binarios</a> para la instalación de Mercurial, tanto para GNU/Linux como para Windows, y esa es la forma recomendada para su instalación.</p>
<p>El <a href="http://mercurial.berkwood.com/">instalador</a> de Mercurial para win32 tiene, a 5 de septiembre de 2006, su versión <a href="http://mercurial.berkwood.com/binaries/Mercurial-0.9.1.exe">0.9.1</a>.</p>
<p>Es posible también hacer una instalación desde el código fuente usando:</p>
<blockquote><p><code>#python setup.py install</code></p></blockquote>
<p>Además del intérprete de <a href="http://www.python.org">python</a> es necesaria la presencia de un compilador de C (gcc) para compilar las extensiones hechas en ese lenguaje.</p>
<p>Es posible comprobar si Mercurial está correctamente instalado en el sistema llamando a la aplicación desde la línea de comandos y comprobando que devuelve información sobre la versión instalada:</p>
<blockquote><p><code><strong>$ hg</strong></p>
<p>Mercurial Distributed SCM (version 0.9.1)</p>
<p>Copyright (C) 2005 Matt Mackall <mpm@selenic.com><br />
This is free software; see the source for copying conditions. There is NO<br />
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.<br />
</code></p></blockquote>
<h1>Personalización del programa</h1>
<h2>Archivos de configuración</h2>
<p>Las personalizaciones para todo el sistema se hacen en <strong>~/.hgrc</strong>, o en<strong> ~/Mercurial.ini</strong> si trabajamos en windows, aunque es posible personalizar el funcionamiento de Mercurial para cada repositorio usando en archivo <strong>.hgrc</strong> en el directorio de trabajo.</p>
<h2>Usuario, editor y nivel de información</h2>
<p>Cada envío de cambios al repositorio de un proyecto almacena datos sobre el usuario que realiza el cambio. Para que esa información sea correcta es necesario proporcionar esa información mediante una opción en la línea de comandos (<em>-u username</em>), o, más cómodamente, aportándola en el archivo de configuración, en el apartado <em>username</em> del bloque <em>[ui]</em>.</p>
<p>Otro de los datos que se incluye en los cambios es un mensaje que explica el cometido de los cambios. Ese texto se puede aportar en la línea de comandos con la opción <em>-m mensaje</em>, o utilizando un editor para escribir el comentario. El editor que abrirá Mercurial para introducir el texto se configura en el apartado <em>editor</em> del bloque <em>[ui]</em> del archivo de configuración.</p>
<p>Una opción global interesante, para que Mercurial sea un poco más locuaz en su operación, es <em>-v</em>, que puede seleccionarse por defecto en el archivo de configuración mediante el apartado <em>verbose</em> del bloque <em>[ui]</em>.</p>
<blockquote><p><code><br />
    [ui]<br />
    # editor por defecto (gvim o el que sea):<br />
    editor = gvim<br />
    # pedir indicación de archivos cambiados:<br />
    verbose=True</p>
<p>    # usuario que se usa al indicar quién hace los cambios:<br />
    username="Pepito Pérez &lt;pepito@perez.org&gt;"<br />
</code></p></blockquote>
<h2>Reconciliación de cambios</h2>
<p>Cuando se desean combinar las distintas versiones de un archivo (merge) es posible utilizar programas que facilitan la reconciliación de los cambios que existen entre ellas. Mercurial hace uso de aplicaciones externas para este cometido, que son habituales en sistemas Unix, pero que han de instalarse separadamente en sistemas Windows. A continuación describimos la configuración e instalación del programa kdiff3 para la reconciliación de cambios en windows:</p>
<p><a href="http://kdiff3.sourceforge.net/">Kdiff3</a> dispone de un <a href="http://prdownloads.sourceforge.net/kdiff3/KDiff3Setup_0.9.90.exe?download">instalador de su versión 0.9.90</a> para windows.</p>
<p>Para localizar los cambios entre una versión base (base) y dos versiones que queremos combinar (local, other), Kdiff3 recibe los datos en un órden (base, local, other) distinto al de Mercurial (local, base, other), por lo que es necesario escribir un pequeño script que se encargue de reordenar la información que Mercurial pasa a Kdiff3. Este script, llamado <em><strong>hgmerge.cmd</strong></em> debe tener el siguiente contenido:</p>
<blockquote><p><code>...\path\to\kdiff3.exe --auto -L1 Base -L2 Local -L3 Other %2 %1 %3 -o %1</code></p></blockquote>
<p>En http://www.selenic.com/mercurial/wiki/index.cgi/MergeProgram se proporciona más información sobre la reconciliación de cambios en Mercurial.</p>
<h2>Uso de SSH como protocolo de comunicación</h2>
<p>Mercurial usa HTTP como protocolo nativo de comunicación, aunque es posible usar SSH si tenemos un cliente de ssh instalado, tal como OpenSSH y, en algún caso, se personaliza la configuración de Mercurial. Esta configuración se explica en la tercera parte de esta serie de artículos sobre Mercurial. En ésta se explica además cómo acceder a un repositorio remoto usando ssh y claves públicas en lugar de contraseñas.</p>
<blockquote><p>NOTA: Todas las aplicaciones externas de las que hace uso Mercurial, tal como ssh, vim o kdiff3, deben estar en la ruta por defecto (PATH) del usuario o del sistema para que Mercurial pueda localizarlas</p></blockquote>
<h1>Uso de Mercurial</h1>
<p>Antes de explicar más detalles, es necesario señalar que Mercurial tiene su propio sistema de ayuda que nos será de utilidad a la hora de conocer los detalles de cada comando y para localizar el comando adecuado a nuestras necesidades.</p>
<p>En el <a href="http://www.selenic.com/mercurial/wiki/index.cgi">wiki del proyecto</a> se puede consultar la lista de preguntas frecuentes además de otras informaciones detalladas de instalación, configuración, etc&#8230; En sistemas Unix/Linux es posible también usar las páginas del manual.<br />
Las opciones generales y una lista de órdenes básicas se pueden consultar con:</p>
<blockquote><p><code>$ hg help</code></p></blockquote>
<p>Para obtener ayuda sobre una orden en particular:</p>
<blockquote><p><code>$ hg help orden</code></p></blockquote>
<h2>Creación de un repositorio</h2>
<p>La creación de un repositorio de Mercurial consiste en la creación de un directorio con algunos metadatos. La orden <strong>init</strong> es la responsable de crear los metadatos y el directorio de trabajo:</p>
<blockquote><p><code>$ hg init nombre-repositorio</code></p></blockquote>
<p>Si se omite el nombre del repositorio, se puede convertir el directorio actual en un repositorio de Mercurial:</p>
<blockquote><p><code>$ hg init</code></p></blockquote>
<h2>Incorporación de archivos al repositorio para rastrear sus cambios</h2>
<p>Para que Mercurial rastree los cambios en un archivo que se encuentra en el directorio de trabajo es necesario incorporarlo al repositorio. Para ello se usa la orden <em>add</em>, con el nombre de los archivos como parámetros.</p>
<blockquote><p><code>$ hg add nombrearchivo1 nombrearchivo2 ...</code></p></blockquote>
<h2>Estado del directorio de trabajo</h2>
<p>Es posible conocer el estado de los archivos del directorio de trabajo en relación a su seguimiento por Mercurial utilizando la orden <em>status</em>.</p>
<blockquote><p><code>$ hg status</code><br />
? c.txt<br />
M a.txt
</p></blockquote>
<p>La orden status devuelve una lista de archivos precedidos por un caracter indicador de estado. Los más importantes son:</p>
<ul>
<li>M &#8211; el archivo contiene modificaciones que no se han registrado en el repositorio</li>
<li>A &#8211; el archivo está marcado para ser añadido al repositorio en el siguiente envío de cambios o &#8220;commit&#8221;</li>
<li>? &#8211;  el archivo no está siendo seguido por Mercurial</li>
</ul>
<h2>Envío de cambios al repositorio</h2>
<p>Cuando se realizan modificaciones en los archivos seguidos por Mercurial es posible guardar ese conjunto de cambios (changeset) en el repositorio local utilizando la orden <em>commit</em>.</p>
<blockquote><p><code>$ hg commit</code></p></blockquote>
<p>Esta orden abre una sesión en el editor de textos que se haya configurado para la introducción de un texto que sirva de aclaración a los cambios guardados. Es posible indicar una cadena de texto en la línea de comandos para su uso en el registro de cambios, sin necesidad de utilizar el editor, y también inidicar un usuario como responsable de los cambios:</p>
<blockquote><p><code>$ hg commit -u 'Pepito Pérez &lt;pepito@perez.org&gt;' -m "El propósito de los cambios es blah blah"</code></p></blockquote>
<h2>Bitácora de cambios</h2>
<p>Se puede ver una lista de los conjuntos de cambios que se han ido haciendo a lo largo de la historia de un proyecto.</p>
<blockquote><p><code>"$ hg log"</code><br />
changeset:   2:f27f5477492b1d40d138e087485877659427c23b<br />
tag:         v1.0<br />
user:        Paco Pérez &lt;pepito@perez.org&gt;<br />
date:        Tue Jun 13 22:55:24 2006 +0200<br />
files:       a.txt b.txt<br />
description:<br />
El propósito de los cambios es blah blah</p>
<p>changeset:   1:797bf3bff932f8c36c9be4ec323f88fb524239ec<br />
user:        Paco Pérez &lt;pepito@perez.org&gt;<br />
date:        Tue Jun 13 22:30:52 2006 +0200<br />
files:       a.txt<br />
description:<br />
Modificar a.txt</p>
<p>changeset:   0:cb3e6e73d53bab2462e38cedc6fa68eef4e70217<br />
user:        &#8220;Usuario de prueba &lt;prueba@cielito.sindominio.net&gt;&#8221;<br />
date:        Tue Jun 13 22:25:17 2006 +0200<br />
files:       a.txt b.txt<br />
description:<br />
Guardamos versiones iniciales de los archivos a.txt y b.txt.
</p></blockquote>
<p>En la bitácora de cambios podemos ver los metadatos asociados a cada changeset:</p>
<ul>
<li>changeset: Identificación del conjunto de cambios mediante: &#8216;número de revisión:changeset ID&#8217;. El número de revisión proporciona una referencia válida solamente para cada copia del repositorio, mientras que el changeset ID constituye una referencia absoluta, incluso entre copias en distintas máquinas.</li>
<li>user: identificación del usuario bajo el que se registra el conjunto de cambios</li>
<li>date: fecha, hora y zona horaria en la que se registró el conjunto de cambios</li>
<li>files: archivos implicados en el conjunto de cambios</li>
<li>description: texto descriptivo de los cambios</li>
</ul>
<p>Tras esta serie de conjuntos de cambios la historia del proyecto sería algo similar a:</p>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/09/hg-commit-00.gif" alt="Commit de Mercurial" /></p>
<p>y el dirstate, o changeset padre del directorio de trabajo se encuentra en la revisión 2, la señalada en rojo en el diagrama.</p>
<h2>Recuperación de revisiones</h2>
<p>Podemos recuperar el estado del directorio tal como estaba tras una revisión determinada. Esta operación, llamada actualización del repositorio, permite recorrer la historia del proyecto y resulta útil para poder ver el estado de los distintos archivos en una revisión determinada, ver los cambios hechos tras importar algunos cambios desde un repositorio externo, o para situarse en un punto diferente del proyecto para crear una nueva rama a partir de él.</p>
<p>La orden que nos permite realizar la actualización de un repositorio es <em>update</em>.</p>
<blockquote><p><code>$ hg update <em>revision</em></code></p></blockquote>
<p><strong>Update</strong> toma como parámetro <em>revisión</em> el changeset al que se desea actualizar. Es posible indicar dicho changeset mediante el número de revisión, un &#8216;tag&#8217;, o con el changeset ID. Mercurial es capaz de reconocer un changeset ID si se le pasa una parte inequívoca de la cadena alfanumérica que lo define, sin necesidad de indicar la cadena completa.</p>
<p>En el ejemplo anterior, si realizamos las siguientes operaciones:</p>
<blockquote><p><code>$ hg update 797b</code></p></blockquote>
<p>ó</p>
<blockquote><p><code>$ hg update 1</code></p></blockquote>
<p>cambiaríamos la revisión que se visualiza en el directorio de trabajo a la revisión <em>1:797bf3bff932f8c36c9be4ec323f88fb524239ec</em>. En la historia del proyecto, nos situaríamos en el estado del proyecto tras el envío del segundo conjunto de cambios:</p>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/09/hg-update-00.gif" alt="Commit de Mercurial" /></p>
<p>Si se omite el parámetro de revisión en la orden update, entonces se presupone la revisión <strong><em>&#8216;tip&#8217;</em></strong> (el último conjunto de cambios guardado).</p>
<p>En nuestro ejemplo,</p>
<blockquote><p><code>$ hg update</code></p></blockquote>
<p>nos llevaría de nuevo a la última revisión del proyecto:</p>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/09/hg-update-01.gif" alt="Mercurial - update a tip" /></p>
<h2>Visualización de diferencias entre revisiones</h2>
<p>Se pueden ver las diferencias entre dos versiones:</p>
<blockquote><p><code>$ hg diff -r version1 -r versión2</code></p></blockquote>
<p>ó</p>
<blockquote><p><code>$ hg diff -r version1:version2</code></p></blockquote>
<p>, entre una versión y la versión del directorio de trabajo:</p>
<blockquote><p><code>$ hg -r version1</code></p></blockquote>
<p>, o entre el changeset padre del directorio de trabajo y los cambios en el directorio de trabajo:</p>
<blockquote><p><code>$ hg diff</code></p></blockquote>
<p>Las versiones, como en el resto de órdenes de Mercurial, se pueden indicar con el número de revisión, el Changeset ID o un tag.</p>
<h2>Copia de repositorios y ramas (branches)</h2>
<p>Se puede clonar un repositorio, de manera que sea posible recuperar datos de su &#8220;original&#8221; para integrar los cambios en uno u otro sentido. La orden <strong>clone</strong> es la usada para este cometido.<br />
Esta operación es muy habitual, puesto que permite la creación de repositorios para realizar desarrollos paralelos que pueden integrarse posteriormente en el repositorio original, trasladar cambios entre uno u otro, o mantener permanentemente versiones con cometidos diferenciados. Una forma de uso frecuente es el desarrollo de funcionalidades en ramas separadas, para integrarlas en el repositorio principal una vez que la implementación de los cambios ha madurado.</p>
<p>La orden</p>
<blockquote><p><code>$ hg clone repositorio-original repositorio-copiado</code></p></blockquote>
<p>clona el repositorio &#8216;<em>repositorio-original</em>&#8216;, haciendo una copia llamada &#8216;<em>repositorio-copiado</em>&#8216;.</p>
<p>La historia de ambos proyectos se mantiene igual,<br />
<img src="http://blog.rvburke.com/wp-content/uploads/2006/09/hg-clone-00.gif" alt="Mercurial - clonar ramas" /><br />
y, además, el repositorio copiado guarda la ruta al repositorio original (<strong>default path</strong> o ruta por defecto). Enn algunas operaciones de traslado de información entre repositorios, si se omite la ruta de trabajo, se utiliza la ruta por defecto. En el siguiente apartado se presentan algunas órdenes donde esta funcionalidad resulta cómoda.</p>
<blockquote class="nota"><p><strong>NOTA:</strong> Para diferenciar dos repositorios relacionados en nuestros ejemplos diferenciaremos sus números de revisión mediante un apóstrofe. Hemos de recordar que estos números de revisión son propios de cada repositorio, ya que simplemente indican el orden en el que se almacenó un changeset en la historia de ese repositorio. Sin embargo, dos changeset idénticos (de idéntica historia y contenidos) tienen el mismo changeset ID, aunque difieran en sus números de revisión.</p></blockquote>
<h2>Traslado de información entre repositorios (push y pull)</h2>
<p>Se pueden trasladar las modificaciones entre repositorios mediante las órdenes <em>push</em> y <em>pull</em>.<br />
<em>Push</em> integra en un repositorio remoto los conjuntos de cambios del repositorio actual que no se encuentren en él, mientras que <em>pull</em> realiza la operación inversa, integra en el repositorio local los cambios adicionales que contenga el repositorio remoto.<br />
En ambas operaciones es neceario indicar la dirección o URL de destino (push) u origen (pull) de la operación.</p>
<blockquote><p><code>$ hg push repositorio-destino</code></p></blockquote>
<p>ó</p>
<blockquote><p><code>$ hg pull repositorio-origen</code></p></blockquote>
<p>Es preciso advertir que estas operaciones simplemente trasladan los cambios entre repositorios, pero no alteran el estado del directorio de trabajo. Si se actualizar el directorio de trabajo al último changeset es probable que se quiera hacer después traer cambios de otro repositorio:</p>
<blockquote><p><code>$ hg update</code></p></blockquote>
<p>que actualiza a <em>tip</em>.</p>
<p>En nuestros repositorios de ejemplo, si se hubiesen guardado cambios distintos en cada uno de ellos, tendríamos unos nuevos changeset 3&#8242; y 3, el dirstate de cada uno de los repositorios se correspondería a estos nuevos changeset, y la historia de ambos repositorios quedaría así:</p>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/09/hg-pushpull-00.gif" alt="Mercurial - push y pull - estado inicial" /></p>
<p>Se puede apreciar cómo las tres primeras revisiones comparten su <strong>changeset ID</strong> (abreviado en el dibujo por comodidad), puesto que son conjuntos de cambios idénticos, mientras que el nuevo changeset de cada repositorio, a pesar de compartir el mismo número de revisión (3), tiene un <strong>changeset ID</strong> diferente. Esto se debe a que no son cambios idénticos.</p>
<p>Si trabajamos desde el repositorio B, cuyo <em>default path</em> apunta al repositorio desde el que fue clonado (el A), podemos traer los cambios de A hasta B simplemente usando la orden <strong>pull</strong>, y aprovechando el default path. También es posible trabajar desde A y llevar los cambios a B con la orden <strong>push</strong> e indicando la ruta a B (puesto que A no tiene un <em>default path</em> que apunte a B):</p>
<blockquote><p><code>$ hg pull</code></p></blockquote>
<p>ó</p>
<blockquote><p><code>$ hg push /ruta/a/repoB</code></p></blockquote>
<p>El gráfico que representa la historia de ambos proyectos quedaría así:</p>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/09/hg-pushpull-01.gif" alt="Mercurial - pull de A a B" /></p>
<p>En el diagrama se observa que el conjunto de cambios <em>3&#8242;:e48f</em> de A se traslada a B como el changeset de número de revisión 4, manteniendo su changeset ID <em>e48f&#8230;</em>.</p>
<p>Como consecuencia de la operación que hemos realizado aparece una nueva cabeza de desarrollo en el repositorio B, coincidente con el changeset 4, al compartir las revisiones 3 y 4 el mismo padre 2.</p>
<p>Otro resultado es que la marca <strong>tip</strong> en B pasa a referenciar al changeset 4, mientras que el <strong>dirstate</strong> en B no se modifica (representado en rojo). Es decir, no se aprecian cambios en el directorio de trabajo, mientras que la revisión <strong>tip</strong>, que antes coincidía con el número de revisión 3, pasa ahora al changeset con número de revisión 4, que es el añadido en último lugar.</p>
<p>Si deseásemos cambiar a la nueva cabeza, podríamos hacer simplemente:</p>
<blockquote><p><code>$ hg update</code></p></blockquote>
<p>ó</p>
<blockquote><p><code>$ hg update 4</code></p></blockquote>
<p>ó</p>
<blockquote><p><code>$ hg update e48f</code></p></blockquote>
<p>La primera opción nos actualiza a tip, mientras que en las dos siguientes se especifica explícitamente la revisión o el changeset ID. El resultado final es que el repositorio queda en el siguiente estado:<br />
<img src="http://blog.rvburke.com/wp-content/uploads/2006/09/hg-pushpull-02.gif" alt="Mercurial - actualizar a tip en la cabeza nueva" /><br />
y que haría que viésemos en el directorio de trabajo el estado del proyecto tal como se encuentra en la nueva revisión 4 del repositorio B (o la 3&#8242; del repositorio A).</p>
<h2>Visualización de las distintas cabezas de un proyecto</h2>
<p>Cuando integramos los cambios de distintos repositorios mediante <em>push</em> o <em>pull</em>, hemos visto que es probable que se produzcan desarrollos paralelos que den lugar a distintas ramas de desarrollo en el proyecto.</p>
<p>Para localizar las distintas cabezas existentes en el repositorio utilizamos la orden <strong>heads</strong>:</p>
<blockquote><p><code>$ hg heads</code><br />
changeset:   3:c22f5477492b1d40d138e087485877659427c23b<br />
tag:         v1.0<br />
user:        Paco Pérez &lt;pacoperez@susitio.com&gt;<br />
date:        Tue Jun 23 22:55:24 2006 +0200<br />
files:       a.txt b.txt<br />
description:<br />
Cambios preparados en el repositorio B para&#8230;</p>
<p>changeset:   4:348ff3bff932f8c36c9be4ec323f88fb624239ec<br />
user:        Paco Pérez &lt;pacoperez@susitio.com&gt;<br />
date:        Tue Jun 23 22:36:52 2006 +0200<br />
files:       a.txt<br />
description:<br />
Cambios preparados en el repositorio A para&#8230;</p></blockquote>
<p>, que nos muestra los changeset que son cabeza de una rama, y refleja las dos cabezas de nuestro ejemplo. En él acabábamos con dos cabezas (números de revisión 3 y 4) tras traer algunos cambios del repositorio A al repositorio B, por haberse producido desarrollos paralelos en ellos:</p>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/09/hg-pushpull-01.gif" alt="Mercurial - pull de A a B" /></p>
<p>Los changeset 3 y 4 definen dos ramas de desarrollo en el repositorio que se  bifurcan en el changeset 2.</p>
<h2>Integración de ramas divergentes (merging)</h2>
<p>A menudo no se pretende que las ramas que se producen en un proyecto permanezcan como desarrollos paralelos de forma indefinida. Para reintegrar los cambios de una rama en otra rama es preciso realizar los siguientes pasos:</p>
<ul>
<li>Indicar la revisión que se desea integrar con el directorio de trabajo mediante la orden <strong>merge</strong>.</li>
<li>Reconciliar los cambios entre las ramas haciendo los cambios necesarios (normalmente con la ayuda de un programa al efecto, por ejemplo, kdiff3, o con nuestro editor preferido).</li>
<li>Guardar el resultado con una operación de <strong>commit</strong>, en un nuevo cambio llamado <strong>merge changeset</strong> o <strong>changeset de mezcla</strong>.</li>
</ul>
<p>La orden <strong>merge</strong> requiere como parámetro el changeset que define la revisión que queremos integrar en la rama actual del directorio de trabajo.</p>
<p>En nuestro ejemplo, para integrar (o mezclar) la rama con número de revisión 3 en la rama de nuestro directorio de trabajo (la 4, ya que la última vez cambiamos el dirstate a la revisión 4 mediante una operación de update) debemos realizar los siguientes pasos:</p>
<p>Indicamos que queremos mezclar la rama 3:</p>
<blockquote><p><code>$ hg merge 3</code></p></blockquote>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/09/hg-merge-00.gif" alt="Merge entre changeset 3 y 4" /></p>
<p>Hacemos los cambios necesarios para reconciliar los cambios al código en ambas ramas&#8230;</p>
<p>y hacemos un commit de mezcla:</p>
<blockquote><p><code>$ hg commit -m "Merge desde la rama 3"</code></p></blockquote>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/09/hg-merge-01.gif" alt="Merge changeset" /></p>
<p>Tras la mezcla solamente nos resta una cabeza, la correspondiente al changeset de mezcla, el 5, y que habrá de reflejarse en la salida de la orden <strong>heads</strong>:</p>
<blockquote><p><code>$ hg heads</code><br />
changeset:   5:676bf3bff932f8c36c9be4ec323f88fb624239ec<br />
user:        Paco Pérez &lt;pacoperez@susitio.com&gt;<br />
date:        Mon Jun 29 12:16:52 2006 +0200<br />
files:       a.txt b.txt<br />
description:<br />
Merge desde la rama 3</p></blockquote>
<p>La etapa intermedia de reconciliación de cambios solamente puede automatizarse parcialmente. Mercurial lanza una aplicación auxiliar para facilitar ese trabajo. La aplicación utilizada es configurable, auque se recomienda el uso de kdiff3, meld o vimdiff.<br />
De todos modos, siempre se deben supervisar los cambios hechos, puesto que el significado preciso de la integración de dos ramas es una cuestión semántica que no siempre puede coincidir con la mezcla por comparación que realizan estas herramientas. Estas permiten, sin embargo, localizar las secciones de código que entran en conflicto (por modificar las mismas zonas del proyecto) y precisan de edición manual, y además realizan una mezcla automática en las secciones en las que no se producen conflictos entre las dos revisiones implicadas, haciendo uso de la información adicional que supone saber cuál es su ancestro común (el changeset en donde se produce la ramificación).</p>
<h1>Organización de los repositorios</h1>
<p>Una manera bastante práctica para organizar los repositorios de un proyecto es la siguiente:</p>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/09/organizacion-repos.gif" alt="Jerarquía de repositorios en Mercurial" /></p>
<p>En esta organización podemos observar los siguientes elementos:</p>
<ul>
<li>Un repositorio personal para cada desarrollador en el que cada uno sube su versión &#8220;pública&#8221; del proyecto. En el diagrama inferior se identifican como repositorios A, B, C o D. Fundamentalmente sirve como backup del trabajo personal y también para que los demás puedan ver los cambios sobre los que está trabajando cada uno. Desde él se suben (push) los cambios al repositorio de integración, al tiempo que sigue los cambios en el repositorio de integración (con pull) para realizar mezclas limpias.</li>
<li>Un repositorio de integración de cambios (crew) al que se llevan los cambios propuestos por los desarrolladores para la versión estable y desde el que se suben (push) los cambios al repositorio principal.</li>
<li>El repositorio principal, &#8220;canónico&#8221; (main), que sirve de referencia pública del proyecto. Recoge los cambios &#8220;contrastados&#8221; del repositorio de integración.</li>
</ul>
<p>Los repositorios en las partes superiores del diagrama toman como referencia los repositorios en las zonas inferiores, y van integrando los cambios que se producen en ellos mediante operaciones <strong>pull</strong>. De esa manera, el código está cada vez más auditado a medida que se avanza en el proceso.</p>
<p>Estos repositorios se encuentran publicados en un servidor (o varios), pero lo más habitual es que los denominados repositorios personales sean a su vez repositorios de integración de otros repositorios locales en los que se hace el desarrollo efectivo. Así, cada desarrollador trabaja en sus repositorios locales sobre nuevas funcionalidades, corrección de errores, etc, y va actualizando (<strong>push</strong>) los cambios consolidados a su repositorio público de usuario.</p>
<p>Cuando una nueva funcionalidad del repositorio público personal está lista para formar parte de la siguiente versión estable se pasa (<strong>push</strong>) desde cada uno de los repositorios personales al repositorio de integración (crew), donde se va probando, y pasa a ser la base sobre la que trabajan los desarrolladores (se actualizan desde él). Es la versión en desarrollo &#8220;en pruebas&#8221;.</p>
<p>En un momento dado se decide lanzar una nueva versión &#8220;estable&#8221;, se corrigen solamente fallos en la versión de pruebas(crew), y, finalmente, se actualiza con ella el repositorio &#8220;estable&#8221; (main).</p>
<h1>Ejemplo de uso en el proyecto Pascaline</h1>
<p>Se han organizado los repositorios publicados en el servidor así:</p>
<ul>
<li>un repositorio principal (main)</li>
<li>un repositorio de integración de cambios (crew)</li>
<li>tres repositorios personales (coya, ramon, pachi)</li>
</ul>
<p>Cada uno trabaja sobre ramas locales que exporta a su repositorio personal y va integrando los cambios que se van generando en el repositorio de integración de cambios, para seguir el desarrollo que vayan haciendo los demás y poder integrar limpiamente los cambios propios en él sin generar nuevas ramas (cabezas) en dicho repositorio.</p>
<p>Se puede clonar el repositorio main así:</p>
<blockquote><p><code>$ hg clone http://hg.rvburke.com/pascaline/main/ pascaline-main</code></p></blockquote>
<p>el repositorio crew así:</p>
<blockquote><p><code>$ hg clone http://hg.rvburke.com/pascaline/crew/ pascaline-crew</code></p></blockquote>
<p>y el mío (pachi, o ramon, o coya):</p>
<blockquote><p><code>$ hg clone http://hg.rvburke.com/pascaline/pachi/ pascaline-pachi</code></p></blockquote>
<p>esto genera en nuestro sistema de archivos los directorios: pascaline-main, pascaline-crew y pascaline-pachi, que son tres repositorios de Mercurial.</p>
<p>para ir actualizándolo con los cambios que se vayan subiendo, simplemente se hace (dentro del directorio pascaline-main, pascaline-crew o pascaline-pachi):</p>
<blockquote><p><code>$ hg pull<br />
$ hg update</code></p></blockquote>
<p>El primero trae los cambios remotos que no se encuentren ya en nuestra copia del repositorio y los guarda en el almacén de conjuntos de cambios, mientras que el segundo actualiza el estado del directorio al último cambio (&#8216;tip&#8217;, por defecto).<br />
hg pull no necesita aquí que se le indique el repositorio de origen porque, al clonarlo, almacena la referencia a la situación del repositorio de referencia (su dirección o su ruta en el sistema de archivos).</p>
<p>Uno puede trabajar en el proyecto de forma más segura haciendo otra copia local, y dejando esos repositorios como copias &#8220;limpias&#8221; del repositorio publicado en el servidor:</p>
<blockquote><p><code>$ hg clone pascaline-pachi pascaline-pachi-para-trastear</code></p></blockquote>
<p>Cambiamos algo y vamos guardando los pasos que queramos a medida que avanzamos en el desarrollo:</p>
<blockquote><p><code>$ hg commit -m "He añadido una cosa a lo de pachi"</code></p></blockquote>
<p>Esta orden (dentro de pascaline-pachi-para-trastear) guarda los cambios hechos como un nuevo changeset, por ejemplo, el 199.<br />
(Podemos ver con <em>hg log</em> cuál es el último).</p>
<p>Para integrar los cambios en otras copias del proyecto podemos optar por hacer un parche de cada conjunto de cambios:</p>
<blockquote><p><code>$ hg diff -r 199 > parche199.diff</code></p></blockquote>
<p>o bien:</p>
<blockquote><p><code>$ hg export 199 > parche199.mercurial</code></p></blockquote>
<p>Esta última opción, <em>export</em>, genera más información útil para Mercurial que un simple parche con diff, y se puede integrar en otro repositorio con </p>
<blockquote><p><code>$ hg import parche199.mercurial</code></p></blockquote>
<p>O bien exportar a un archivo el lote cambios que no existe en el repositorio de destino. Las ordenes bundle y unbundle permiten generar e integrar esos archivos:</p>
<blockquote><p><code>$ hg bundle cambios.bundle path/a/repo-destino</code></p></blockquote>
<p>y (en el directorio del repositorio de destino):</p>
<blockquote><p><code>$ hg unbundle cambios.bundle</code></p></blockquote>
<p>Pero la forma más práctica y potente de trasladar los cambios es con <em>push</em> y <em>pull</em>.</p>
<p>Desde pascaline-pachi podemos traer los cambios desde pascaline-pachi-para-trastear así:</p>
<blockquote><p><code>$ hg pull pascaline-pachi-para-trastear</code></p></blockquote>
<p>o, desde pascaline-pachi-para-trastear, podemos llevar los cambios a pascaline-pachi:</p>
<blockquote><p><code>$ hg push pascaline-pachi</code></p></blockquote>
<p>en pascaline-pachi actualizamos a los últimos cambios:</p>
<blockquote><p><code>$ hg update</code></p></blockquote>
<p>y podemos subir los cambios al repositorio en el servidor de la misma manera, con push:</p>
<blockquote><p><code>$ hg push http://hg.rvburke.com/pascaline/pachi/</code></p></blockquote>
<p>ó, al usar la dirección por defecto (desde la que hemos clonado pascaline-pachi),</p>
<blockquote><p><code>$ hg push</code></p></blockquote>
<p>Los cambios que tenemos en el repositorio local deberían aparecer ahora en el repositorio publicado en el servidor.<br />
El proceso es el mismo para trasladar cambios entre los directorios personales y crew, entre crew y main o entre cualesquiera otros repositorios.</p>
<h1>&#8230;y en el próximo capítulo&#8230;</h1>
<p>La próxima parte de esta serie de artículos tratará sobre la configuración del servidor para la publicación de repositorios, así como la configuración del acceso con ssh y claves públicas.</p>
<div class="copyright">(c) Rafael Villar Burke 2006<br />
Se permite la copia, distribución y modificación de este texto siempre que se conserve el copyright y esta nota.</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.rvburke.com/2006/09/08/control-de-versiones-con-mercurial-ii-uso-de-mercurial/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Control de Versiones con Mercurial (I) &#8211; Conceptos generales</title>
		<link>http://blog.rvburke.com/2006/08/25/control-de-versiones-con-mercurial-i-conceptos-generales/</link>
		<comments>http://blog.rvburke.com/2006/08/25/control-de-versiones-con-mercurial-i-conceptos-generales/#comments</comments>
		<pubDate>Fri, 25 Aug 2006 17:31:49 +0000</pubDate>
		<dc:creator>pachi</dc:creator>
				<category><![CDATA[castellano]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[programación]]></category>
		<category><![CDATA[software-libre]]></category>

		<guid isPermaLink="false">http://blog.rvburke.com/2006/08/25/control-de-versiones-con-mercurial-i-conceptos-generales/</guid>
		<description><![CDATA[Introducción En este artículo se hace una introducción a los conceptos necesarios para el trabajo con sistemas de control de versiones. En particular, se orienta al aprendizaje de Mercurial, un sistema de control de versiones de última generación y carácter distribuido escrito por Matt Mackall. El artículo forma parte de una serie que se publicará [...]]]></description>
			<content:encoded><![CDATA[<p><a class="imagelink" href="http://blog.rvburke.com/wp-content/uploads/2006/09/mercurial-logo.png" title="Mercurial - Logo"><img class="floatleft" id="image46" src="http://blog.rvburke.com/wp-content/uploads/2006/09/mercurial-logo.thumbnail.png" alt="Mercurial - Logo" /></a></p>
<h2>Introducción</h2>
<p>En este artículo se hace una introducción a los conceptos necesarios para el trabajo con sistemas de control de versiones. En particular, se orienta al aprendizaje de <a href="http://selenic.com/mercurial">Mercurial</a>, un sistema de control de versiones de última generación y carácter distribuido escrito por <em>Matt Mackall</em>.<br />
El artículo forma parte de una serie que se publicará en este <a href="http://blog.rvburke.com">blog</a>, y que se estructura de la siguiente manera:</p>
<ul>
<li>I &#8211; Conceptos generales</li>
<li>II &#8211; Uso de Mercurial</li>
<li>III &#8211; Publicación de proyectos</li>
</ul>
<p><span id="more-18"></span></p>
<h1>Sistemas de control de versiones (VCS)</h1>
<p>Mercurial es un programa que <strong>permite mantener un registro histórico de los cambios realizados en el contenido de un proyecto</strong>. Normalmente se utiliza en proyectos de software, pero se puede utilizar para otros propósitos (elaboración de documentos, archivo de la configuración de un sistema, etc).</p>
<p>Estos programas son conocidos como <strong>sistemas de control de versiones</strong> (<strong>VCS</strong>, por sus siglas en inglés), o sistemas de gestión de código (<strong>SCM</strong>).</p>
<p>La gran ventaja de tener un registro de cambios es la posibilidad de recuperar versiones antiguas, visualizar los cambios hechos entre dos versiones, la seguridad de poder hacer pruebas sabiendo que se pueden deshacer los cambios, la capacidad de reconciliar cambios entre distintas &#8220;ramas&#8221; de un mismo proyecto, etc&#8230;</p>
<h1>Sistemas de control de versiones centralizados y distribuidos (DVCS)</h1>
<p>Tradicionalmente, y en los <strong>sistemas centralizados</strong>, el registro de cambios de un proyecto se almacenaba en un único servidor, que contenía toda la información de su historia, y del que dependían los distintos clientes para realizar operaciones que implicasen modificar o consultar la historia del proyecto. El gran problema de estos sistemas es que deja sin todos los beneficios del uso de un sistema de control de versiones a las personas que no tienen permiso de acceso (fundamentalmente de escritura) al servidor.</p>
<p>Una nueva generación de sistemas de control de versiones, conocidos como <strong>sistemas de control de versiones distribuidos</strong>, permiten que toda la información acerca de la historia de un proyecto no haya de mantenerse en un único archivo central. En estos sistemas cada copia del proyecto contiene esa información, lo que permite que cada persona que trabaja con una copia disponga de todas las ventajas del control de versiones, y se facilita la colaboración, puesto que es posible relacionar los cambios realizados en diferentes copias, localizando su ancestro común a partir del cual se producen divergencias en el código común.</p>
<p>Este nuevo modelo favorece una participación más equitativa en equipos distribuidos y una organización menos jerarquizada, sin impedir por ello la posibilidad de un funcionamiento similar al que exigen los sistemas centralizados.</p>
<p>Si bien puede parecer que el coste de mantener información redundante en cada copia de un proyecto puede ser excesivo, en la práctica rara vez lo es, gracias al uso de técnicas de compresión y la similitud entre versiones sucesivas. Aún en proyectos muy grandes, con amplias historias de cambios, como el kernel <em>Linux</em> o <em>FreeBSD</em>, el espacio ocupado en disco para almacenar la historia de cambios no alcanza apenas al espacio ocupado por los archivos versionados.</p>
<h1>Un poco de vocabulario: repositorios, conjuntos de cambios (Changeset) y estado del directorio (dirstate)</h1>
<p>Mercurial registra la historia de un proyecto almacenando una especie de &#8220;instantáneas&#8221; del mismo en lo que se denomina &#8220;<strong>repositorio</strong>&#8221; (almacén, depósito).<br />
Esas &#8220;instantáneas&#8221;, llamadas <strong>Changeset</strong> o <strong>conjuntos de cambios</strong>, contienen la versión en la que se encuentra cada uno de los archivos que se han &#8220;<strong>añadido</strong>&#8221; al repositorio, y son la pieza fundamental sobre la que se organiza Mercurial.</p>
<p>Así, el changeset <em>235</em> podría tener la versión 1 del archivo leeme.txt, la versión 5 del archivo <em>COPYING</em>, y no registra la existencia del archivo <em>NEWS</em>:</p>
<blockquote><p><code>leeme.txt [versión 1]<br />
COPYING [versión 5]</code></p></blockquote>
<p>Por otra parte, el changeset <em>236</em> contiene el archivo leeme.txt en la misma versión (la 1), el archivo <em>COPYING</em> en la versión 6, y ya ha aparecido el archivo <em>NEWS</em>, en su versión 0:</p>
<blockquote><p><code>leeme.txt [versión 1]<br />
COPYING [versión 6]<br />
NEWS [versión 0]</code></p></blockquote>
<p>El conjunto de changesets de un proyecto podría ser algo así:</p>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/08/mercurial01.gif" alt="Mercurial - historia lineal" /></p>
<p>donde <em>0</em> es el changeset incial y (<em>236</em>) el último changeset registrado. Cada uno de esos estados del proyecto se registra indicando de forma explícita al sistema de control de versiones que se desean registrar los cambios. A esta operación se le conoce como hacer un envío de cambios o &#8220;<strong>commit</strong>&#8220;.</p>
<p>Algunos sistemas de control de versiones usan bases de datos para estructurar la información de los repositorios, pero, en Mercurial, un repositorio no es más que un directorio al que se añaden algunos metadatos. Estos metadatos los gestiona el sistema de forma transparente y automática, y están básicamente formados por los conjuntos de cambios del proyecto, además de por el estado actual del directorio de trabajo o &#8220;<strong>dirstate</strong>&#8220;.</p>
<p>El &#8220;<strong>dirstate</strong>&#8221; es el <strong>changeset padre</strong>, o el changeset del cual parte el contenido actual del directorio de trabajo. Este dato resulta necesario, puesto que el contenido del directorio de trabajo puede corresponder a cualquiera de las versiones registradas del proyecto o a una versión modificada de éstas&#8230; ya que el sistema permite navegar por la historia del proyecto.</p>
<p>En el esquema anterior, el dirstate sería el changeset <em>236</em>, y contendría los siguientes archivos:</p>
<blockquote><p><code>leeme.txt [versión 1]<br />
COPYING [versión 6]<br />
NEWS [versión 0]</code></p></blockquote>
<p>Si modificamos esos contenidos, el changeset padre del directorio de trabajo seguiría siendo el <em>236</em>, aunque los contenidos no serían iguales a dicha versión.</p>
<p>A la operación de recuperar en el directorio de trabajo una versión cualquiera de las registradas en el repositorio se le conoce como &#8220;<strong>actualizar</strong>&#8221; a una versión, y es una de las más útiles y habituales de las que permiten los sistemas de control de versiones.</p>
<p>En el ejemplo anterior, podríamos actualizar el directorio de trabajo a la versión <em>235</em>:</p>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/08/mercurial02.gif" alt="Mercurial - historia lineal" /></p>
<p>de manera que el dirstate corresponde al changeset 235, y el contenido del directorio de trabajo sería:</p>
<blockquote><p><code>leeme.txt [versión 1]<br />
COPYING [versión 5]</code></p></blockquote>
<h1>Ramas, cabezas de desarrollo, reconciliación de cambios y tip</h1>
<p>Hasta ahora hemos visto la historia de un proyecto como un registro lineal, pero lo más habitual es que se produzcan divergencias en la historia del mismo, dando lugar a lo que se conocen como &#8220;ramas&#8221; de desarrollo (&#8220;branches&#8221;).</p>
<p>Un ejemplo de aparición de divergencias es el siguiente:</p>
<ul>
<li>Se publica una nueva versión de un programa (<em>v1.0</em> o changeset <em>212</em>)</li>
<li>Se siguen registrando nuevas funcionalidades en proceso de desarrollo (hasta el changeset <em>215</em>)</li>
<li>Surge un fallo inesperado en la versión publicada que exige la publicación de una nueva versión corregida</li>
<li>Se actualiza el directorio de trabajo a la versión publicada (el dirstate cambia a <em>212</em>)</li>
<li>Se aplican las correcciones necesarias y se registra y publica la nueva versión (v1.1 o changeset <em>216</em>)</li>
<li>Se actualiza el directorio de trabajo para seguir trabajando en las nuevas funcionalidades (el dirstate cambia a <em>215</em>)</li>
<li>Se siguen añadiendo cambios (<em>217</em>)</li>
<li>En este proceso acabamos con dos ramas: una versión incial más las nuevas funcionalidades (rama &#8220;<em>en desarrollo</em>&#8220;), una versión inicial con correcciones de fallos (rama &#8220;<em>estable</em>&#8220;).</li>
</ul>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/08/mercurial03.gif" alt="Mercurial - historia ramificada" /></p>
<p>Al changeset más reciente de cada rama se le conoce como <strong>cabeza</strong> (<strong>head</strong>) de la rama. En nuestro ejemplo serían los changeset <em>216</em> y el <em>217</em>. Al changeset más reciente del repositorio se le conoce como <strong>tip</strong>, y al final del proceso de nuestro ejemplo, sería el changeset <em>217</em>.</p>
<p>En el ejemplo anterior, es imaginable que se desee integrar los cambios de la rama &#8220;<em>estable</em>&#8221; en la rama en &#8220;<em>desarrollo</em>&#8220;.</p>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/08/mercurial04.gif" alt="Mercurial - historia ramificada y merging" /></p>
<p>A este proceso se le denomina reconciliación de cambios, mezcla de ramas, o &#8220;<em>merging</em>&#8220;, y Mercurial realiza esta operación añadiendo un nuevo changeset (<em>218</em>) que unifica dos changeset padre (normalmente las cabezas, en este caso <em>216</em> y <em>217</em>), e incluye en él las modificaciones necesarias para reconciliar los cambios entre ellas.</p>
<h1>Números de revisión, changeset ID y etiquetas</h1>
<p>Hemos visto que la mayor parte de las operaciones, como la actualización a una versión determinada, o la mezcla de ramas, es necesario referirse a los changeset del repositorio. Para ello, Mercurial permite utilizar tres sistemas distintos: el <strong>número de revisión</strong>, el <strong>changeset ID</strong>, o un <strong>tag </strong>(etiqueta).</p>
<p>El número de revisión es simplemente un número natural que corresponde al orden en el que se registró del changeset en el repositorio. Es la forma que hemos usado hasta ahora en los ejemplos, pero presenta el problema de que no identifica de forma única a un determinado changeset, sino que puede cambiar de máquina a máquina, en función de las diferencias en la historia de cada copia de un repositorio. Por ello no es útil más que para referirse a una copia concreta de un repositorio.</p>
<p>El changeset ID es un identificador único para un changeset, que lo identifica en un punto concreto de la historia de un repositorio, y es indepediente de la máquina en la que se sitúe. Permite referirse al mismo changeset en distintas copias de un repositorio. En Mercurial es un dato de 160bits, normalmente representado como una secuencia de 20 caracteres.</p>
<p>Una etiqueta (tag) es simplemente una cadena de texto que se liga a un changeset ID, y permite identificarlo de forma más conveniente. En nuestro ejemplo la etiqueta &#8220;<em>v1.0</em>&#8221; puede estar ligado al changeset ID: <em>58deccf0bead81a34691095db485a19efa1be709</em>, que correspondía al número de revisión <em>212</em>, mientras que el número de revisión <em>216 </em>está marcado con la etiqueta &#8220;<em>v1.1</em>&#8220;. En los esquemas se señalan las etiquetas en cajas amarillas.</p>
<p><img src="http://blog.rvburke.com/wp-content/uploads/2006/08/mercurial04.gif" alt="Mercurial - historia ramificada y merging" /></p>
<h1>&#8230;y en el próximo capítulo&#8230;</h1>
<p>La próxima parte de esta serie de artículos tratará sobre la instalación y el uso práctico de Mercurial.</p>
<blockquote class="nota"><p><strong>NOTA:</strong> El logo de Mercurial se distribuye bajo licencia GPL, según las condiciones establecidas en el sitio web de <a href="http://selenic.com/mercurial">Mercurial</a></p></blockquote>
<div class="copyright">(c) Rafael Villar Burke 2006<br />
Se permite la copia, distribución y modificación de este texto siempre que se conserve el copyright y esta nota.</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.rvburke.com/2006/08/25/control-de-versiones-con-mercurial-i-conceptos-generales/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
