Hiparco

Recetas y trucos de GNU/Linux e informática en general

Alojado en http://guimi.net

Guía rápida de subversión (svn)

Esta entrada no pretende ser una guía completa de subversion, solo una guía rápida para comenzar a trabajar con esta potente herramienta.

Introducción

Muchos proyectos están migrando de Svn a Git ya que Git les aporta una serie de ventajas, principalmente que Git es distribuido (SVN es centralizado). Git parece ser claramente mejor para proyectos grandes y, sobre todo, con mucha gente.
La alternativa a svn+trac sería git+gitorious. Aunque Git parece ser mejor que Svn en algunos aspectos, trac sigue siendo mejor que gitorious.
Aquí tenemos una guía de Git para usuarios de svn.

Antes de empezar

Para organizar los proyectos se suele asumir por convenio crear tres directorios por proyecto:

  • Trunk: Directorio de un repositorio bajo el cual se encuentran los directorios y ficheros de nuestro proyecto.
  • Tag: Directorio bajo el cual se almacenan las diferentes versiones o releases de nuestro software.
  • Branches: Directorio donde se almacenan ramas de nuestro proyecto (por ejemplo, para pruebas de concepto).

Las reglas de oro del trabajo con sistemas de versiones, son dos:

  • Nunca harás un commit de código que no compile o tenga errores: Si lo haces, cuando otro programador haga un update su código también tendrá esos errores y por tanto no compilará.
  • Siempre harás un update antes de empezar a trabajar sobre el código. De esta manera, te aseguras de estar trabajando siempre sobre la última versión del código.

Dicho esto queda recordar que subversion usa por defecto el puerto 3690.

Los comandos principales (hay más) de svn son:

  • Status: Nos indica la situación de nuestra copia local respecto al proyecto en el repositorio.
  • Import: Comando utilizado para subir al repositorio la estructura inicial de nuestro proyecto.
  • Checkout (co): Comando para descargar en un PC un proyecto desde un repositorio.
  • Update (up): Comando que nos permite actualizar nuestro proyecto en local desde el repositorio central.
  • Add: Comando utilizado para añadir un fichero a nuestro proyecto. No es subido al repositorio hasta que se indique con el comando “commit”. El comando add solo deja “marcado” ese fichero o directorio como parte del repositorio.
  • Delete: Comando que permita marcar un fichero o directorio para ser eliminado del respositorio.
  • Commit (ci): Comando que nos permite subir al repositorio todos los cambios hechos sobre un proyecto en local.
  • Log: Consulta el trabajo realizado con un repositorio

 

SERVIDOR SUBVERSION

Primero debemos instalar subversion:
# aptitude install subversion

Crear un repositorio

Generamos un directorio para el repositorio (gestionado por svn, el servidor)
$ mkdir repositorio
$ cd repositorio

Creamos un proyecto, para estos ejemplos usaremos un proyecto llamado “ANA”
$ svnadmin create ANA

Configuramos el acceso. Una configuración habitual es lectura a todo el mundo y escritura a los autorizados.
$ vi ANA/conf/svnserve.conf

[general]
anon-access = read
auth-access = write
realm = My First Repository
password-db = passwd

Generamos los usuarios con permiso de escritura. Las claves van en texto claro, por tanto deberíamos cuidar los permisos de este fichero.
$ vi ANA/conf/passwd

[users]
harry = harryssecret
sally = sallyssecret

Lanzamos el servidor
$ svnserve -d -r /path_de_repositorio/
El parámetro ‘-d’ hace que el servidor se ponga en modo “demonio”.
El parámetro ‘-r’ indica la ruta al repositorio. Si no usamos el parámetro -r, los clientes deben indicar siempre la ruta completa de la carpeta, con los problemas que conlleva de comodidad (ruta muy larga), seguridad (publicidad de la estructura de directorios) y administración (cambios en el sistema de archivos).
 

CLIENTE SVN

Para trabajar con un servidor mediante ssh:
SVN+SSH: Conectar con un servidor svn mediante ssh

Puesta en marcha

Importar un repositorio

Si trabajamos con un servidor preinstalado podemos, como clientes, crear proyectos a partir de unas fuentes pre-existentes mediante “import”:
$ svn import nuevoProyecto http://urlDelRepositorio/ -m “Importacion inicial”
Esto requiere de una configuración un poco más compleja en el servidor.

Creando un nuevo proyecto a partir de fuentes anteriores

En el equipo en que vamos a programar (puede ser el mismo que el servidor) generamos un directorio para la copia local -copia de trabajo- (las fuentes con que trabajamos)
$ mkdir copia_local
$ cd copia_local

Tomamos las fuentes del proyecto (CheckOut – co)
$ svn co svn://localhost/ANA

En la revisión 0.

Copiamos en el nuevo directorio los ficheros fuente del proyecto (si existían).
$ cd ANA
$ cp -R /ruta_fuentes_anteriores/* .

Añadimos los ficheros al proyecto
$ svn add *

Actualizamos la información local sobre los ficheros. Nos indica todos los ficheros que están marcados para ser añadidos al repositorio.
$ svn status

A   fichero1
A   fichero2
...
En la revisión 0.

Hacemos commit (ci) de las modificaciones y dejamos una nota o mensaje (-m)
$ svn ci -m “Importacion inicial”

Uso y disfrute

Lo primero que se debe hacer al empezar a programar es actualizar las fuentes (ver reglas de oro), para asegurarnos que disponemos de la última versión:
$ cd /ruta_copia_local/ANA
$ svn update

Al acabar (si el programa no compila no has acabado -ver reglas de oro-):
– Comprobamos los cambios que tenemos pendientes con:
$ svn status
– Hacemos los ajustes necesarios (svn add, svn delete… ver más adelante).
– Guardamos los cambios con un comentario indicando los cambios realizados.
$ svn ci -m “Cambios blablablabla”

Veamos algunas de las funciones más habituales.

Añadir ficheros

Ya hemos visto en la importación como añadir ficheros, pero lo vamos a volver a ver con un poco más de detalle.
Generamos un nuevo fichero:
$ touch kk
Consultamos la información de los ficheros locales
$ svn status

?       kk

La única diferencia con el repositorio es que hay un fichero kk que no conoce

Añadimos el fichero kk al proyecto
$ svn add kk

A         kk

Consultamos la información de los ficheros locales
$ svn status

A       kk

La única diferencia con el repositorio es que hay un fichero kk por añadir

Hacemos commit (ci) del fichero y dejamos una nota o mensaje (-m)
$ svn ci -m “Prueba add kk”

Añadiendo      kk
Transmitiendo contenido de archivos .
Commit de la revisión 1.

Modificar ficheros

Modificamos el fichero de prueba
$ vi kk
Consultamos la información de los ficheros locales
$ svn status

M       kk

La única diferencia con el repositorio es que hay un fichero kk por modificar

Podemos ver las diferencias entre el fichero local y el del repositorio
$ svn diff kk

Index: kk
===================================================================
--- kk (revisión: 1)
+++ kk (copia de trabajo)
@@ -1,2 +1,3 @@
 #Llalala
+#lilililili
 #lelele

Hacemos commit (ci) del fichero y dejamos una nota o mensaje (-m)
$ svn ci -m “Prueba kk modificado”

Commit de la revisión 2.

Consultamos la información de los ficheros locales
$ svn status
No hay diferencias con el repositorio

Conflictos con ficheros

Si existen varios desarrolladores, puede ocurrir un conflicto al “subir” un fichero que haya sido modificado desde que hicimos el update.
$ svn ci -m “Forzamos conflicto”

Enviando       kk
svn: Falló el commit (detalles a continuación):
svn: Desactualizado: 'kk' en transacción '5-1'

$ svn status

M      ejemplo2.py

Podemos abreviar ‘update’ como ‘up’
$ svn up

C    ejemplo2.py
Actualizado a la revisión 3.

Al encontrar el conflicto, SVN genera 4 ficheros, uno con el conflicto, el local, el de la revisión anterior (r2) y el de la nueva revisión (r3).
$ ls -l

...
-rw-r--r-- 1 guimi guimi 111 2007-07-09 19:51 kk
-rw-r--r-- 1 guimi guimi  49 2007-07-09 19:51 kk.mine
-rw-r--r-- 1 guimi guimi  29 2007-07-09 19:51 kk.r2
-rw-r--r-- 1 guimi guimi  57 2007-07-09 19:51 kk.r3

Tras corregir el conflicto, indicamos que lo hemos resuelto:
$ vi kk
$ svn resolved ejemplo2.py

Se resolvió el conflicto de 'ejemplo2.py'

Al marcar el conflicto como resuelto, SVN borra los ficheros de resolución.

Volvemos a realizar el commit.
$ svn ci -m “Conflicto resuelto”

Borrar ficheros

Probamos a borrar un fichero de nuestro disco duro
$ rm kk
Consultamos la información de los ficheros locales
$ svn status

!       kk

La diferencia con el repositorio es que localmente falta un fichero

Si actualizamos la información del repositorio…
$ svn update

Se restituyó 'kk'
En la revisión 2.

…recuperamos el fichero borrado.
Para eliminar un fichero del proyecto debemos indicar al sistema que lo elimine del repositorio.
Quitamos un fichero del proyecto (y lo borramos de nuestro disco duro)
$ svn delete kk
Quitamos otro fichero del repositorio, pero mantenemos la copia local
$ svn delete –keep-local kk2
Consultamos la información de los ficheros locales
$ svn status

D         kk
D         kk2

La única diferencia con el repositorio es que hay dos fichero por eliminar.

Hacemos commit (ci) de las modificaciones y dejamos una nota o mensaje (-m)
$ svn ci -m “Borrado de ficheros”

Eliminando     kk
Eliminando     kk2
Commit de la revisión 3.

Renombrar ficheros

$ svn mv kk ejemplo

A         ejemplo
D         kk

$ svn status

D      kk
A  +   ejemplo

$ svn commit –message “Cambio de nombre”

Eliminando     ejemplo1.py
Añadiendo      ejemplo2.py

Commit de la revisión 3.

Consultar el trabajo realizado

Vemos todo el trabajo que hemos realizado
$ svn log

------------------------------------------------------------------------
r4 | guimi | 2012-02-07 20:52:05 +0100 (mar 07 de feb de 2012) | 1 line

Prueba del kk
------------------------------------------------------------------------
r3 | guimi | 2012-02-07 20:51:39 +0100 (mar 07 de feb de 2012) | 1 line

Prueba add kk
------------------------------------------------------------------------
r2 | guimi | 2012-02-07 20:39:46 +0100 (mar 07 de feb de 2012) | 1 line

Prueba
------------------------------------------------------------------------
r1 | guimi | 2012-02-07 20:33:02 +0100 (mar 07 de feb de 2012) | 1 line

Importacion inicial
------------------------------------------------------------------------

podemos consultar el trabajo que hemos realizado respecto a un fichero concreto, por ejemplo AndroidManifest.xml
$ svn log AndroidManifest.xml

------------------------------------------------------------------------
r1 | (sin autor) | 2012-02-07 20:33:02 +0100 (mar 07 de feb de 2012) | 1 line

Importacion version inicial 0.1.5-Beta
------------------------------------------------------------------------
svn, subversion, control de versiones