{"id":605,"date":"2006-12-09T19:02:42","date_gmt":"2006-12-09T17:02:42","guid":{"rendered":"http:\/\/www.marblestation.com\/blog\/?p=605"},"modified":"2012-04-26T16:56:18","modified_gmt":"2012-04-26T14:56:18","slug":"bazaar-ng-bzr-sistema-de-control-de-versiones-distribuido","status":"publish","type":"post","link":"https:\/\/www.marblestation.com\/?p=605","title":{"rendered":"Bazaar-NG (bzr), sistema de control de versiones distribuido"},"content":{"rendered":"<p><a href=\"http:\/\/bazaar-vcs.org\/\">Bazaar-ng<\/a> es un sistema de control de versiones distribuido que, al igual que CVS o Subversion, nos permite guardar progresivamente los cambios que vayamos realizando sobre un conjunto de archivos de texto (habitualmente c\u00f3digo fuente), recuperar versiones anteriores, mostrar diferencias, integrar el trabajo de diversos programadores, etc&#8230;<\/p>\n<p>Sin embargo, a diferencia de CVS o Subversion, Bazaar-ng nos permite trabajar de formas mucho m\u00e1s flexibles&#8230; desde el t\u00edpico esquema cliente-servidor hasta la descentralizaci\u00f3n de los repositorios, tal y como veremos m\u00e1s adelante en el apartado de flujos de trabajo.<\/p>\n<p>Para instalarlo en Ubuntu:<\/p>\n<pre>\r\naptitude install bzr \r\n<\/pre>\n<p>Veamos como podemos trabajar con Bazaar&#8230;<br \/>\n<!--more--><\/p>\n<h2>T\u00e9rminos<\/h2>\n<p>Antes de empezar a utilizar Bazaar-NG, debemos entender una serie de t\u00e9rminos:<\/p>\n<ul>\n<li>Working Tree: C\u00f3digo fuente con el que el programador puede trabajar. Todo \u00e1rbol de trabajo est\u00e1 siempre asociado a una rama (branch).<\/li>\n<li>Branch: Guarda el c\u00f3digo fuente y el hist\u00f3rico de cambios que se han realizado sobre \u00e9l. Adicionalmente, se nos permite crear nuevas ramas a partir de una rama, trabajar con ella de forma independiente (con su correspondiente control de versiones) y una vez hayamos acabado podemos volver a fusionarla con la rama inicial. <br \/>\n<blockquote><p>\n   Veamos un peque\u00f1o caso pr\u00e1ctico: tenemos una rama base con el c\u00f3digo estable y queremos a\u00f1adir una nueva funcionalidad sin afectar a la estabilidad de ese c\u00f3digo. Creamos una nueva rama de desarrollo basada en la rama estable, trabajamos con ella y una vez terminada la nueva funcionalidad y ha sido testeada, fusionamos con la rama estable.\n<\/p><\/blockquote>\n<\/li>\n<li>Repository: Las ramas de un \u00fanico proyecto son muy similares dado que son copias de la misma base junto a nuevas modificaciones, mantener toda esta informaci\u00f3n duplicada puede consumir bastante espacio innecesariamente. Si las ramas son guardadas en un repositorio, estas no mantendr\u00e1n cada una sus revisiones sino que lo gestionar\u00e1 el repositorio, evitando as\u00ed la duplicidad de informaci\u00f3n y optimizando el espacio usado.<\/li>\n<\/ul>\n<p>Cabe destacar que es posible tener la rama (branch) y el \u00e1rbol de trabajo (working tree) en un mismo directorio, o mantenerlos en directorios separados. Este \u00faltimo caso se suele utilizar para tener las revisiones de control en un servidor centralizado y los \u00e1rboles de trabajo en los ordenadores de los desarrolladores.<\/p>\n<h2>Flujos de trabajo o Workflows<\/h2>\n<p>Como ya he apuntado previamente, con Bazaar-NG tenemos la posibilidad de trabajar de una forma m\u00e1s flexible que CVS o Subversion, adapt\u00e1ndose al flujo de trabajo que queramos utilizar:<\/p>\n<ul>\n<li>Centralizado o Lock-Step: Concepto de trabajo igual que el aplicado por Subversion o CVS con la ventaja de una gesti\u00f3n de ramas mejorada mediante un repositorio.<\/li>\n<li>Lock-Step con commits locales: Igual que el anterior pero los desarrolladores realizan commits locales sin modificar el servidor hasta que consideran oportuno actualizarlo. Tenemos la ventaja de reducir el n\u00famero de commits err\u00f3neos que interfieran en el trabajo del resto de desarrolladores.<\/li>\n<li>Descentralizado con linea principal compartida: Cada programador tiene su propia rama adem\u00e1s de permisos en la rama principal. Cada uno trabaja en su rama personal (commit) y cuando lo consideran apropiado, lo fusionan con la rama principal (pull, merge). Ventajas:\n<ul>\n<li>Organizaci\u00f3n del trabajo sencilla.<\/li>\n<li>Un desarrollador puede fusionar su rama con la de otra persona con la que este trabajando en algo conjuntamente.<\/li>\n<\/ul>\n<\/li>\n<li>Descentralizado con guardi\u00e1n autom\u00e1tico o manual: Cada programador tiene su propia rama y permisos de solo lectura en la rama principal. Cuando un desarrollador quiere fusionar su c\u00f3digo en la linea principal, lo pide al &#8220;guardi\u00e1n&#8221; que se encarga de revisar, compilar y hacer tests unitarios para comprobar que todo es correcto. La ventaja principal radica en que el c\u00f3digo se revisa antes de pasar a la l\u00ednea principal.\n<\/li>\n<\/ul>\n<h2>Configuraci\u00f3n<\/h2>\n<p>La configuraci\u00f3n de Bazaar-NG se debe crear en &#8220;~\/.bazaar\/bazaar.conf&#8221;:<\/p>\n<pre>\r\nmkdir ~\/.bazaar\/\r\ncd ~\/.bazaar\/\r\ntouch bazaar.conf\r\n<\/pre>\n<p>Podemos editar &#8220;bazaar.conf&#8221; y a\u00f1adir:<\/p>\n<pre>\r\n[DEFAULT]\r\nemail             = Your Name &#60;email@isp.com>\r\neditor            = \/usr\/bin\/vim\r\n<\/pre>\n<p>Bazaar-NG requiere que cada desarrollador especifique su nombre e email para as\u00ed registrar y vincular cada uno de los cambios que se realizan al c\u00f3digo, adicionalmente, el hecho de proporcionar el email facilita que cualquier programador pueda ponerse en contacto con alguien que haya realizado un cambio determinado (en caso de proyectos donde participan muchas personas, es de agradecer).<\/p>\n<p>Con la variable &#8220;editor&#8221; indicamos que editor queremos que se ejecute cuando Bazaar-NG requiere que proporcionemos informaci\u00f3n, por ejemplo la explicaci\u00f3n de los cambios cuando queramos actualizar la rama.<\/p>\n<p>En el fichero de configuraci\u00f3n podemos a\u00f1adir de forma opcional: <\/p>\n<pre>\r\ncheck_signatures  = check-available\r\ncreate_signatures = when-required\r\n<\/pre>\n<p>Con check_signatures podemos indicar 3 valores:<\/p>\n<ul>\n<li>require: Para cada actualizaci\u00f3n de c\u00f3digo debe existir una firma gnupg y ser v\u00e1lida.<\/li>\n<li>ignore: No se comprueban firmas gnupg.<\/li>\n<li>check-available: (Valor por defecto) Si existe una firma gnupg para la actualizaci\u00f3n, comprobarla. Bazaar-NG fallar\u00e1 si encuentra una firma incorrecta, pero no si la firma no esta presente.<\/li>\n<\/ul>\n<p>Con create_signatures podemos indicar tambi\u00e9n 3 valores:<\/p>\n<ul>\n<li>always: Firmar cada actualizaci\u00f3n que enviemos.<\/li>\n<li>when-required: (Valor por defecto) Firmar las actualizaciones que enviemos, s\u00f3lo si la rama requiere que as\u00ed lo hagamos.<\/li>\n<li>never: No firmar las actualizaciones que enviemos, aunque la rama as\u00ed lo requiera.<\/li>\n<\/ul>\n<p>Como se puede intuir por las opciones, Bazaar nos permite firmar criptogr\u00e1ficamente (con gnupg) los cambios que realicemos al c\u00f3digo y comprobar a la vez, las firmas de los dem\u00e1s desarrolladores. Esta es una medida de seguridad efectiva para garantizar que los cambios son realmente de quien parecen ser, as\u00ed evitamos que alguna persona mal intencionada intente inyectar c\u00f3digo malicioso en nuestro proyecto.<\/p>\n<p>Finalmente, indicar que hasta ahora hemos configurado la secci\u00f3n &#8220;Default&#8221; que es la configuraci\u00f3n global para todos los repositorios. Podr\u00edamos crear configuraciones espec\u00edficas por ramas:<\/p>\n<pre>\r\n[DEFAULT]\r\nemail             = Your Name &#60;email@isp.com>\r\neditor            = \/usr\/bin\/vim\r\ncheck_signatures  = check-available\r\ncreate_signatures = when-required\r\n\r\n[\/home\/usuario\/rama01]\r\nemail             = Your Name &#60;other_email@isp.com>\r\n<\/pre>\n<h2>Creaci\u00f3n de repositorios y ramas (Flujo de trabajo descentralizado)<\/h2>\n<p>Con tal de poder empezar a trabajar con Bazaar-NG siguiendo un esquema de trabajo descentralizado, tenemos 2 posibilidades:<\/p>\n<ul>\n<li>Crear un repositorio y una rama base: Si en el futuro generamos nuevas ramas derivadas de la base dentro del repositorio, el historial de cambios ser\u00e1 gestionado por el repositorio y no se duplicar\u00e1 informaci\u00f3n.<br \/>\n\t<center><br \/>\n\t\t<img decoding=\"async\" src=\"http:\/\/static.flickr.com\/125\/317779599_111315b88b.jpg?v=0\"\/><br \/>\n\t<\/center><\/p>\n<p>\tInstrucciones (se crear\u00e1 &#8220;directorio-repo&#8221; para el repositorio y &#8220;estable&#8221; para la rama):<\/p>\n<pre>\r\n## Creaci\u00f3n del repositorio en local donde las ramas y los directorios de trabajo estar\u00e1n en el mismo directorio\r\nbzr init-repo --trees directorio-repo\/\r\n\r\n# Creaci\u00f3n de la rama base\r\nbzr init directorio-repo\/estable\r\n\t<\/pre>\n<p>\t<i>* El par\u00e1metro &#8220;&#8211;trees&#8221; crea un repositorio que contendr\u00e1 ramas y directorios de trabajo conjuntamente, para que solo contenga ramas usar\u00edamos &#8220;&#8211;no-trees&#8221;.<\/i><\/p>\n<\/li>\n<li>Crear directamente una rama base: Podemos crear una rama base sin estar contenida en ning\u00fan repositorio. En este caso, para cada rama derivada que creemos se duplicar\u00e1 el historial de cambios y por tanto ser\u00e1 menos \u00f3ptimo \u00fanicamente en t\u00e9rminos de espacio.\n<p>\t<center><br \/>\n\t\t<img decoding=\"async\" src=\"http:\/\/static.flickr.com\/123\/317779598_2210ef3fd3.jpg?v=0\"\/><br \/>\n\t<\/center><br \/>\n\tInstrucciones (se crear\u00e1 el directorio &#8220;estable&#8221; para la rama):<\/p>\n<pre>\r\n# Creaci\u00f3n de la rama base\r\nbzr init estable\r\n\t<\/pre>\n<\/li>\n<\/ul>\n<p>A partir de este punto, ya podemos trabajar en el directorio &#8220;estable&#8221; creando\/copiando nuevos ficheros de c\u00f3digo fuente.<\/p>\n<p>Si quisi\u00e9ramos crear ramas derivadas de la rama base, utilizar\u00edamos:<\/p>\n<pre>\r\n# Creaci\u00f3n de una rama\r\nbzr branch directorio-repo\/estable directorio-repo\/desarrollo\r\n<\/pre>\n<p>Si estamos usando un repositorio, lo ideal es crear la nueva rama dentro del mismo repositorio para aprovechar as\u00ed las ventajas ya comentadas. De hecho, podemos crear ramas derivadas de  &#8220;desarrollo\/&#8221; llamadas por ejemplo &#8220;usuario01&#8221;, &#8220;usuario02&#8221;, etc&#8230; as\u00ed cada usuario trabajar\u00eda en su parte del desarrollo con ramas independientes que pueden fusionarse entre ellas. Estas nuevas ramas podr\u00edan situarse dentro del propio directorio &#8220;desarrollo\/&#8221; tal y como muestra el esquema gr\u00e1fico anterior. En instrucciones:<\/p>\n<pre>\r\nbzr branch directorio-repo\/desarrollo directorio-repo\/desarrollo\/usuario01\r\n<\/pre>\n<p>En cualquier caso, tambi\u00e9n podemos crear ramas en cualquier otro directorio fuera del repositorio (de hecho, si no estamos usando repositorio, esto ser\u00e1 lo habitual).<\/p>\n<h2>Fusi\u00f3n de ramas<\/h2>\n<p>Siguiendo los ejemplos de la secci\u00f3n anterior, es posible que nos interese fusionar el trabajo de la rama &#8220;desarrollo&#8221; en la rama &#8220;estable&#8221;:<\/p>\n<pre>\r\n# Juntar rama con la base\r\ncd estable\r\nbzr merge ..\/desarrollo\r\nbzr commit\r\n<\/pre>\n<h2>Creaci\u00f3n de repositorios y ramas (Flujo de trabajo centralizado)<\/h2>\n<p>Si queremos empezar a trabajar con Bazaar-NG siguiendo un flujo de trabajo centralizado o Lock-Step con commits locales (ver secci\u00f3n de flujos de trabajo), necesitamos crear un repositorio y una rama base. Estas pueden ser creadas localmente tal y como se ha mostrado en la secci\u00f3n anterior, o en un servidor remoto utilizando SSH:<\/p>\n<pre>\r\n## Creaci\u00f3n del repositorio en remoto donde las ramas no contendran los directorios de trabajo, y por tanto se debe hacer un branch\/checkout para poder trabajar\r\nbzr init-repo --no-trees sftp:\/\/centralhost\/directorio-repo\/\r\n\r\n# Creaci\u00f3n de la rama base\r\nbzr init sftp:\/\/centralhost\/directorio-repo\/estable\r\n<\/pre>\n<p>En este punto hemos creado un repositorio centralizado con una rama en el directorio &#8220;estable&#8221;. Dado que el repositorio centralizado solo contiene una rama sin directorio de trabajo, no se puede trabajar directamente en el directorio &#8220;estable&#8221;, sino que debemos generarnos un directorio de trabajo aparte. Para ello utilizaremos el comando checkout, de esta forma estaremos forzando a Bazaar-NG a trabajar contra el servidor:<\/p>\n<pre>\r\nbzr checkout sftp:\/\/centralhost\/directorio-repo\/estable estable\r\n<\/pre>\n<p>Para la creaci\u00f3n de ramas centralizadas, las generaremos dentro del repositorio del servidor para a continuaci\u00f3n descargarlas mediante un chechout:<\/p>\n<pre>\r\n# Creaci\u00f3n de una rama\r\nbzr branch sftp:\/\/centralhost\/directorio-repo\/estable sftp:\/\/centralhost\/directorio-repo\/desarrollo\r\n\r\nbzr checkout sftp:\/\/centralhost\/directorio-repo\/desarrollo desarrollo\r\n<\/pre>\n<p>Bazaar-NG nos permite realizar dos tipos de checkout diferentes:<\/p>\n<ul>\n<li>LightweightCheckout: Unicamente se descarga el c\u00f3digo:\n<pre>\r\nbzr checkout --lightweight sftp:\/\/centralhost\/directorio-repo\/estable estable\r\n\t<\/pre>\n<ul>\n<li>Ventajas: Consume menos ancho de banda.<\/li>\n<li>Desventajas: Tenemos que trabajar siempre con acceso al servidor remoto.<\/li>\n<\/ul>\n<\/li>\n<li>HeavyweightCheckout: Se descarga el c\u00f3digo y el historial.\n<pre>\r\nbzr checkout sftp:\/\/centralhost\/directorio-repo\/estable estable\r\n\t<\/pre>\n<ul>\n<li>Ventajas: Si no tenemos acceso al servidor, podemos ir guardando los cambios a nuestro c\u00f3digo de forma local (par\u00e1metros: commit &#8211;local) o desasociarse del servidor (par\u00e1metro: unbind). Si hemos desasociado y m\u00e1s adelante volvemos a tener conexi\u00f3n con el servidor, podemos volver a asociarnos  (par\u00e1metro: unbind) y actualizar ahora el servidor.<\/li>\n<li>Desventajas: Consume m\u00e1s ancho de banda.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Situaciones \u00fatiles para trabajar de forma centralizada:<\/p>\n<ul>\n<li>M\u00faltiples programadores que quieren trabajar con un c\u00f3digo constantemente actualizado entre ellos.<\/li>\n<li>Un \u00fanico programador que utiliza diferentes m\u00e1quinas y quiere mantener el c\u00f3digo sincronizado en todas ellas<\/li>\n<\/ul>\n<h2>Uso de Bazaar-NG<\/h2>\n<p>Hasta este momento hemos visto como configurar Bazaar-NG, crear repositorios y ramas para flujos de trabajo centralizados y descentralizados. En este secci\u00f3n nos centraremos en el uso habitual de la herramienta una vez ya disponemos de todo lo necesario para trabajar.<\/p>\n<p>Para familiarizarnos con la herramienta, seguiremos todo un conjunto de instrucciones partiendo de la creaci\u00f3n de una rama base local:<\/p>\n<pre>\r\nmkdir test\r\ncd test\r\nbzr init\r\n<\/pre>\n<p>Dentro de esta rama &#8220;test&#8221; podemos ver su estado:<\/p>\n<pre>\r\nbzr status\r\n<\/pre>\n<p>Como no hemos hecho ning\u00fan cambio, este comando no visualizar\u00e1 nada. Probamos a crear un fichero vacio:<\/p>\n<pre>\r\ntouch main.cs\r\nbzr status\r\n<\/pre>\n<p>Esta vez Bazaar-NG nos indicar\u00e1 que hay un fichero que no se encuentra gestionado por el control de versiones:<\/p>\n<pre>\r\nunknown:\r\n  main.cs\r\n<\/pre>\n<p>Otra forma de ver este tipo de informaci\u00f3n:<\/p>\n<pre>\r\nbzr unknowns\r\n<\/pre>\n<p>Para incluir el fichero &#8220;main.cs&#8221; en el control de versiones:<\/p>\n<pre>\r\nbzr add main.cs \r\n<\/pre>\n<p>A\u00f1adimos una l\u00ednea al ficheor &#8220;main.cs&#8221;:<\/p>\n<pre>\r\n$ echo \"Hola mundo\" >> main.cs\r\n<\/pre>\n<p>Ahora nuestro directorio de trabajo contiene modificaciones respecto al control que lleva Bazaar-NG, si queremos mostrar las diferencias:<\/p>\n<pre>\r\nbzr diff\r\n<\/pre>\n<p>Lo que nos mostrar\u00e1:<\/p>\n<pre>\r\n=== added file 'main.cs'\r\n--- main.cs     1970-01-01 00:00:00 +0000\r\n+++ main.cs     2006-10-18 20:39:03 +0000\r\n@@ -0,0 +1,1 @@\r\n+Hola mundo\r\n<\/pre>\n<p>En este momento podemos actualizar el sistema de control de versiones con una nueva versi\u00f3n de nuestro c\u00f3digo, para ello debemos especificar un mensaje descriptivo con los cambios que hemos realizado al c\u00f3digo:<\/p>\n<pre>\r\nbzr commit -m \"hola mundo en main.cs\"\r\n<\/pre>\n<p>Si no indicasemos el mensaje con el par\u00e1metro &#8220;-m&#8221;, se ejecutar\u00eda el editor del sistema (ver secci\u00f3n configuraci\u00f3n) para que introdujesemos la descripci\u00f3n. Una vez realizado el commit, por pantalla se mostrar\u00e1:<\/p>\n<pre>\r\nadded main.cs\r\nCommitted revision 1.\r\n<\/pre>\n<p>Acabamos de guardar la primera revisi\u00f3n de nuestro c\u00f3digo.<\/p>\n<p>Imaginemos que por error borramos el fichero &#8220;main.cs&#8221;:<\/p>\n<pre>\r\nrm main.cs\r\n<\/pre>\n<p>Podemos recuperarlo mediante:<\/p>\n<pre>\r\nbzr revert ## Recupera la \u00faltima versi\u00f3n\r\n<\/pre>\n<p>Es posible que a medida que trabajemos en nuestro proyecto, haya ficheros que queremos que sean ignorados por Bazaar-NG, como por ejemplo las t\u00edpicas c\u00f3pias de seguridad de algunos editores (ficheros acabados en *~). Para ello creamos el fichero &#8220;.bzignore&#8221; con los patrones de ficheros a ignorar:<\/p>\n<pre>\r\necho \"*~\" >> .bzrignore\r\n<\/pre>\n<p>Para probar la configuraci\u00f3n, creamos un fichero que cumple el patr\u00f3n y indicamos a Bazaar-NG que nos liste los ficheros que ser\u00e1n ignorados:<\/p>\n<pre>\r\ntouch main.cs~\r\nbzr ignored\r\n<\/pre>\n<p>Efectivamente nos tiene que mostrar &#8220;main.cs~&#8221;.<\/p>\n<p>Por comodidad, el fichero de configuraci\u00f3n de ignorados &#8220;.bzignore&#8221; tambi\u00e9n debe ser a\u00f1adido al sistema de gesti\u00f3n de versiones:<\/p>\n<pre>\r\nbzr add .bzrignore\r\nbzr commit -m \"Add ignore patterns\"\r\n<\/pre>\n<p>Acabamos de incorporar la segunda revisi\u00f3n.<\/p>\n<p>Si queremos visualizar las diferencias entre revisiones podemos usar:<\/p>\n<pre>\r\n# Diferencias entre la revisi\u00f3n 0 y la 2\r\nbzr diff -r 0..2 \r\n\r\n# Diferencias entre la revisi\u00f3n 0 y la \u00faltima\r\nbzr diff -r 0..\r\n\r\n# Diferencias entre la revisi\u00f3n inicial y la 2\r\nbzr diff -r ..2\r\n<\/pre>\n<p>A continuaci\u00f3n, creamos un directorio &#8220;src&#8221; con un fichero &#8220;simple.c&#8221; y lo a\u00f1adimos:<\/p>\n<pre>\r\nmkdir src\r\necho 'int main() {}' > src\/simple.c\r\nbzr add src\r\n<\/pre>\n<p>Bazaar-NG a\u00f1ade de forma recursiva todo el contenido del directorio:<\/p>\n<pre>\r\nadded src\r\nadded src\/simple.c\r\n<\/pre>\n<p>A\u00f1adimos la nueva revisi\u00f3n con el nuevo directorio y fichero:<\/p>\n<pre>\r\nbzr commit -m \"Simple!\"\r\n<\/pre>\n<p>Si en este punto borramos por completo el directorio &#8220;src&#8221; y preguntamos a Bazaar-NG cual es el estado:<\/p>\n<pre>\r\nrm -rf src\/\r\nbzr status\r\n<\/pre>\n<p>Detectar\u00e1 autom\u00e1ticamente ficheros borrados f\u00edsicamente:<\/p>\n<pre>\r\nremoved:\r\n  src\/\r\n  src\/simple.c\r\n<\/pre>\n<p>Y en el pr\u00f3ximo commit los considerar\u00e1 como borrados. Por otro lado, si creamos un fichero como por ejemplo &#8220;complex.c&#8221;:<\/p>\n<pre>\r\necho 'int main() {}' > complex.c\r\nbzr add complex.c\r\nbzr commit -m \"Borrado src\"\r\n<\/pre>\n<p>Y lo intentamos borrar mediante:<\/p>\n<pre>\r\nbzr remove complex.c\r\n<\/pre>\n<p>Bazaar-NG hace que el fichero deje de estar versionado, pero no lo borra fisicamente del directorio actual. Debemos ser nosotros quienes llevemos a cabo esa tarea de forma espec\u00edfica, igual que hicimos con el directorio &#8220;src&#8221;.<\/p>\n<p>Ahora creamos una rama a partir de la rama &#8220;test&#8221; tal y como hemos visto en secciones anteriores:<\/p>\n<pre>\r\ncd ..\r\nbzr branch test\/ test-rama-derivada\r\n<\/pre>\n<p>Ahora podriamos entrar a la nueva rama:<\/p>\n<pre>\r\ncd test-rama-derivada\r\n<\/pre>\n<p>Y veriamos que contiene lo mismo que la rama original &#8220;test&#8221;. Podriamos trabajar en esta rama mientras otras personas trabajan en la &#8220;test&#8221; en paralelo, e ir actualizando nuestra rama con la rama &#8220;test&#8221; mediante:<\/p>\n<pre>\r\nbzr pull\r\n<\/pre>\n<p>Si han habido cambios en &#8220;test&#8221;, los intenta integrar en &#8220;test-rama-derivada&#8221; (que es donde hemos ejecutado el comando anterior).<\/p>\n<p>Por el contrario, si lo que queremos hacer es actualizar &#8220;test&#8221; con el contenido de &#8220;test-rama-derivada&#8221; ejecutaremos:<\/p>\n<pre>\r\nbzr merge\r\n<\/pre>\n<p>En caso de que aparezcan conflictos, por ejemplo un fichero llamado &#8220;file.c&#8221; ha sido modificado en ambas ramas, se generar\u00e1n en nuestra rama local los siguientes ficheros:<\/p>\n<ul>\n<li>file.c: Fichero mezclado con las 2 versiones y se\u00f1alado el punto de conflicto mediante s\u00edmbolos &#8220;&#60;&#60;&#60;&#8221; y &#8220;>>>&#8221;.<\/li>\n<li>file.c.BASE: Versi\u00f3n anterior del control de versiones de tu rama.<\/li>\n<li>file.c.OTHER: Versi\u00f3n de la otra rama.<\/li>\n<li>file.c.THIS: Versi\u00f3n local de tu rama.<\/li>\n<\/ul>\n<p>Podemos utilizar programas como diff (consola) o meld (gr\u00e1fico) para ver las diferencias entre el fichero OTHER y THIS, quedandonos con los cambios que nos convengan (quiz\u00e1s este es un buen momento en el que se tiene que contactar con los otros programadores para decidir que hacer). Una vez tengamos la versi\u00f3n definitiva, la guardamos en &#8220;file.c&#8221; y borramos los otros 3 ficheros (BASE, OTHER y THIS).<\/p>\n<p>A continuaci\u00f3n se indica a Bazaar-NG que el conflicto ha sido resuelto, hacemos commit a nuestra rama e intentamos volver a hacer el merge:<\/p>\n<pre>\r\nrm *.BASE *.OTHER *.THIS\r\nbzr resolve file.c\r\nbzr commit -m \"conflictos resueltos\"\r\nbzr merge\r\n<\/pre>\n<p>Para evitar los conflictos, lo ideal es que se defina muy bien el objetivo de cada desarrollador, dividiendo las tareas a realizar y evitando solaparse trabajando sobre los mismos ficheros. Pero llegado el caso, ya hemos visto que puede ser sencillo controlar los posibles conflictos que puedan surgir con Bazaar-NG.<\/p>\n<h2>Herramientas gr\u00e1ficas<\/h2>\n<p>Si queremos disponer de ayudas visuales para realizar las tareas m\u00e1s habituales, podemos instalar el paquete &#8220;bzr-gtk&#8221;:<\/p>\n<pre>\r\naptitude install bzr-gtk\r\n<\/pre>\n<p>De esta forma tendremos nuevos par\u00e1metros para el comando &#8220;bzr&#8221;:<\/p>\n<ul>\n<li>&#8220;bzr gcommit&#8221;: Nos mostrar\u00e1 gr\u00e1ficamente los ficheros que se van a subir y tendremos una caja de texto donde a\u00f1adir la pertinente descripci\u00f3n.<\/li>\n<li>&#8220;bzr gdiff&#8221;: Podremos ver en una ventana y con resaltado de sintaxis las diferencias entre las revisiones que indiquemos<\/li>\n<li>&#8220;bzr visualise&#8221;: Muestra gr\u00e1ficamente el historial de cambios listando programadores, descripciones de cambios, conflictos, etc&#8230;<\/li>\n<li>&#8220;bzr gannotate <i>fichero<\/i>&#8220;: Muestra gr\u00e1ficamente los cambios realizados a un fichero en concreto durante la diferentes revisiones.<\/li>\n<li>&#8220;bzr gbranch&#8221;: Nos permite crear una rama a partir de otra.<\/li>\n<\/ul>\n<p>Finalmente, para visualizar y tratar diferencias entre ficheros, recomiendo la aplicaci\u00f3n <a href=\"http:\/\/meld.sourceforge.net\/\">meld<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bazaar-ng es un sistema de control de versiones distribuido que, al igual que CVS o Subversion, nos permite guardar progresivamente los cambios que vayamos realizando sobre un conjunto de archivos de texto (habitualmente c\u00f3digo fuente), recuperar versiones anteriores, mostrar diferencias, integrar el trabajo de diversos programadores, etc&#8230; Sin embargo, a diferencia de CVS o Subversion, &hellip; <a href=\"https:\/\/www.marblestation.com\/?p=605\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Bazaar-NG (bzr), sistema de control de versiones distribuido<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,6],"tags":[],"class_list":["post-605","post","type-post","status-publish","format-standard","hentry","category-espanyol","category-tecnologia"],"_links":{"self":[{"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/posts\/605","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=605"}],"version-history":[{"count":1,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/posts\/605\/revisions"}],"predecessor-version":[{"id":1315,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=\/wp\/v2\/posts\/605\/revisions\/1315"}],"wp:attachment":[{"href":"https:\/\/www.marblestation.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=605"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=605"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.marblestation.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=605"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}