Curso Subversion: Utilización básica

Uso básico de subversion

Para pedir ayuda

Todos los comandos de subversion ofrecen ayuda, muy detallada por cierto, a través del argumento help.

svn help
svn help checkout, por ejemplo
svnadmin help
svnsync help

Posiblemente help sea el argumento más utilizado de todos cuando se usa la interfaz de comandos.

Creación de un repositorio

Un repositorio es un sistema de ficheros diseñado para llevar la cuenta de todos los cambios realizados y registrados en sus ficheros y directorios mediante un cliente de subversion. Los clientes de subversion acceden al repositorio mediante una URL. La parte de protocolo de esta url depende de la manera en que se haya configurado el acceso al repositorio:

Dentro del mismo servidor siempre será posible acceder directamente a través del sistema de ficheros mediante file://, el resto de tipos de acceso sirven para acceder al repositorio a través de la red.

La creación de un repositorio es independiente de la manera en que se pueda accede a él, y se hace desde el mismo servidor en que se vaya a ubicar el repositorio mediante el comando:

svnadmin create [URL]

por ejemplo:

svnadmin create /var/lib/svn/curso-svn

Crearía el repositorio curso-svn en ubicación /var/lib/svn, el cual ya sería accesible desde la misma máquina mediante un cliente de subversion.

Importar un directorio a un repositorio

A partir de este momento supondremos que tenemos un repositorio accesible mediante HTTP. Por eso usaremos como forma de URL: http://.

svn import /Users/juanda/Apps/cursos/curso_svn/MapBundle/ http://curso-svn.juandarodriguez.es/svn/mapbundle -m 'importacion inicial'

El repositorio debe estar creado en el servidor. El directorio local no se convierte en copial local del repo.

Otra forma de realizar la importación inicial de un repositorio es la siguiente; se mete uno en el directorio que se quiere importar, y se hace:

svn co http://curso-svn.juandarodriguez.es/svn/mapbundle .
svn add *
svn commmit -m 'importacion inicial'

La ventaja es que el directorio importado se convierte en copia local.

Igual que antes, el repo debe estar creado en el servidor.

Crear una copia de trabajo

Para trabajar en el desarrollo del proyecto es indispensable contar con una copia de trabajo local del repositorio (o de la parte del repositorio que nos interese).

svn co http://curso-svn.juandarodriguez.es/svn/mapbundle
o
svn co http://curso-svn.juandarodriguez.es/svn/mapbundle nombre_dir

Ciclo de trabajo básico

Una vez que tenemos la copia de trabajo ya podemos comenzar a trabajar en el proyecto. Los pasos típicos que se siguen cuando se trabaja con código bajo control de versiones son:

  1. Actualizar la copia de trabajo (svn update).
  2. Realizar cambios. Es decir, trabajar en el proyecto.
  3. Revisar los cambios (svn diff y svn status).
  4. Arreglar tus errores (svn revert).
  5. Mezclar el código con los cambios que se hayan realizado mientras trabajabas (svn update), posiblemente haya que arreglar conflictos.
  6. Enviar al repositorio (svn commit).

Cuando se vuelva al trabajo, se repite este ciclo.

Cuando se realizan cambios, para que el cliente de subversion los registre, hay que tener en cuenta:

En lo que sigue, cuando hablemos de item nos referimos a un fichero, directorio o enlace simbólico.

Actualizar la copia de trabajo

Se hace con svn update. Durante esta fase:

  • los nuevos items que hayan en el repositorio simplemente se añaden,
  • los items que hayan sido borrados en el repositorio y que no hayan sido modificados localmente, se elimana de la copia local,
  • los items que hayan sido borrados en el repositorio y que hayan sido modificados localmente, darán lugar a un conflicto que habrá que resolver manualmente,
  • los items existentes se mezclan con los de la copia local (merge). Si no había cambios locales simplemente se mezclan los nuevos cambios. En el caso de que hubiera cambios locales y remotos, subversion intentará mezclarlos, pero en algunos casos, por ejemplo cuando se ha tocado la misma línea, no podrá hacerlo y arrojará un conflicto que habrá que resolver manualmente.

Los conflictos únicamente pueden ocurrir cuando se actualiza una copia de trabajo con modificaciones. Por tanto pueden ocurrir justamente antes de enviar los cambios al repositorio, ya que mientras se modificaba la copia de trabajo, algún otro desarrollador ha podido enviar cambios al repositorio.

Los códigos que se muestran en las operaciones de actualización son los siguientes:

  • A -> cuando se añade un item,
  • G -> cuando se ha mezclado automaticamente un item,
  • C -> cuando se ha producido un conflicto.

Por otro lado, en algunas ocasiones puede ser útil actualizar la copia de trabajo a una revisión concreta.

svn update -r 4

La resolución de conflictos la explicamos al final de esta unidad.

Revisando los cambios realizados

Para saber los items que se han cambiado mientras se trabaja en la copia local:

  • svn status, resumen de los cambios que has realizado en la copia local,
  • svn status -u, resumen de los cambios que has realizado en la copia local marcando los items desactualizados, esto es, que han sufrido cambios en el repo mientras tanto.

Si se añade el modificador -v, se da un resumen detallado de todos los cambios.

Los códigos que muestra svn status al inicio de cada línea son:

  • ? item, el item no está bajo control de versión.
  • A item, el item ha sido marcado para ser añadido en el repo.
  • C item, hay un conflicto con el item. Es decir, los cambios recibidos cuando se actualizó la copia de trabajo, no pudieron mezclarse automáticamente por que había partes que se solapaban. Hay que resolver manualmente estos conflictos.
  • D item, el item ha sido marcado para ser borrado en el repo.
  • M item, El contenido del item ha sido modificado en la copia local.

Para saber los cambios que se han realizado dentro de un fichero concreto se usa svn diff fichero o svn diff si se quiere mostrar los cambios realizados dentro de todos los ficheros modificados.

Los códigos que muestra svn diff al principio de cada línea son:

  • un espacio, no se ha cambiado la línea.
  • +, se ha añadido esa línea.
  • -, se ha eliminado esa línea.

La salida de svn diff es compatible con el programa patch, por lo que resulta muy útil para crear parches y distribuirlos.

Si se quiere volver a poner un fichero como estaba antes de modificarlo se usa svn revert. También se puede usar este comando para desmarcar un fichero o directorio que haya sido marcado para ser añadido, borrado, movido o copiado. En definitiva para colocarlo exactamente como estaba antes de su modificación o adición. Si no existía, pues se elimina.

Enviando cambios al repositorio

Una vez realizados los cambios, revisados, y actualizados (mezclados) con los posibles cambios que se hayan producido en el repositorio, lo cual puede obligar a arreglar algún que otro conflicto, es el momento de enviar los cambios al repositorio. Esto se hace con el comando svn commit:

svn commit -m 'mensaje ilustrativo de los cambios'

También podemos enviar ficheros sueltos:

svn commit fichero1 ... ficheroN -m 'mensaje ilustrativo de los cambios'

Es muy importante que el mensaje asociado al commit sea lo más claro y descriptivo posible.

Además de este conjunto de operaciones habituales, subversion ofrece muchas más opciones para inspeccionar y obtener información del repositorio.

Examinando la historia

Subversion es como una máquina del tiempo: cada commit genera una revisión que es una "fotografía" del código en el momento en que se hizo el commit. Por ello proporciona herramientas para examinar con detalle la historia de los items de un repositorio.

svn diff

Además de servir para ver los cambios de nuestra copia local, también se puede usar para:

  • ver los cambios de nuestra copia local con una revisión del repo:
svn diff -r 4 ficher
  • ver los cambios entre dos revisiones:
svn diff -r 2:4
svn diff -r 4:2

El primer comando muestra las diferencia de la revisión 4 respecto de la 2 y el segundo el de la revisión 2 respecto de la 4. Si en la salida del primero aparece una linea que se ha añadido, en la del segundo esa misma línea aparece como eliminada.

svn log

Este comando nos pemite ver el historial de cambios realizado en el repositorio completo o en un fichero concreto.

  • svn log, historial de todos los cambios
  • svn log fichero, historial de un fichero
  • svn log -r 5:9, historial entre las revisiones 5 y 9
  • svn log -r 8, historial de la revisión 8
  • svn log --diff, se obtiene, además información acerca de los cambios producidos dentro de los ficheros.
  • svn log http://curso-svn.juandarodriguez.es/svn/mapbundle, muestra el historial del repositorio mapbundle completo
  • svn log http://curso-svn.juandarodriguez.es/svn/mapbundle/trunk, muestra el historial del directorio trunk del repositorio mapbundle completo

Inspeccionando el repositorio

Lo más cómodo es usar la aplicación websvn y utilizar un navegador web. Pero si no se dispone de ella, o no se acuerda uno de la url, o cualquier otra cosa, el cliente subversion ofrece herramientas suficientes para ello.

svn cat

Permite ver el contenido de un archivo en una revisión

svn cat -r4 fichero

svn annotate

Permite ver quien es el responsable de la última modificación y cual fué la última revisión en que se cambió.

  • svn annotate fichero, muestra el contenido anotado de la copia de trabajo,
  • svn annotate fichero -r 4, muestra el contenido anotado de la revisión 4.

Si se añade el modificador -v, se obtiene además la fecha en que se hizo el cambio.

svn list

Muestra los archivos de un repositorio sin hacer una copia local del mismo.

svn list http://curso-svn.juandarodriguez.es/svn/mapbundle

Resolución de conflictos

La resolución de conflictos siempre es un proceso manual en el que hay que andarse con mucho cuidado si no queremos fastidiar el trabajo hecho por otros y romper el software que se está desarrollando.

Un conflicto ocurre cuando varias personas están trabajando en las mismas líneas de un mismo fichero. Una de las personas subirá primero los cambios al repositorio y, por ser el primero, no tendrá ningún problema. Pero cuando alguna de las otras personas actualice su copia de trabajo, se encontrará con que subversion no has sido capaz de fusionar automáticamente los cambios y avisa de que hay un conflicto en dicho fichero.

Vamos a ilustrar la aparición y resolución de un conflicto con un ejemplo.

Supongamos que dos desarrolladores están trabajando sobre el fichero bootstrap.php de un proyecto. Uno de ellos envía los cambios que ha hecho, y el otro, que intenta enviarlos después, no puede por que su copia de trabajo está desactualizada. Procede a actualizarla con svn update y se encuentra lo siguiente:

Updating '.':
Conflict discovered in '/Users/juanda/tmp/trunk2/bootstrap.php'.
Select: (p) postpone, (df) diff-full, (e) edit,
        (mc) mine-conflict, (tc) theirs-conflict,
        (s) show all options: p

Subversion le avisa de que se ha producido un conflicto y le da varias opciones:

Lo más seguro, a menos que se tenga muy claro lo que se está haciendo es posponer la resolución. Entonces si se hace svn st se verá lo siguiente:

C       bootstrap.php
?       bootstrap.php.mine
?       bootstrap.php.r42
?       bootstrap.php.r43

Además de marcarse como "en conflicto" el fichero en cuestión, se han añadido 3 ficheros más.

En el fichero bajo control de versiones se ha hecho una fusión particular; tanto los cambios que vienen del repositorio como los modificados en la copia de trabajo están presentes, pero como coinciden en las misma líneas, subversion ha añadido una marca que indica a qué parte pertenece, si a la revisión que viene del repositorio o a la "mía". Simplemente analizando con cuidado este archivo y borrando lo que no proceda, añadiendo lo que proceda y/o modificando lo que se necesite, se puede resolver el conflicto.

Pero para tener más información y criterios a la hora de resolver podemos usar los ficheros:

Si, por ejemplo, estuviesemos seguros de que es alguno de estos ficheros el bueno, bastaría con copiarlo a bootstrap.php.

Una vez que hemos realizado los cambios oportunos tenemos que indicar a subversion que ya hemos resuelto el conflicto en ese fichero y subir los cambios al repositorio:

svn resolved bootstrap.php
svn commit -m 'mensaje de actualización'

Y el conflicto queda resuelto.

Ramas y fusiones >>>