domingo, 7 de mayo de 2006

Introducción a Subversion / Tutorial de Subversion ( Spanish )



He rescatado este post del 2006, que todavía google lo tenía enlazado.

Introducción a Subversion / Tutorial de Subversion (Spanish)

Submitted by kikov on Sun, 2006-05-07 10:07.


Esta guía está pensada para gente que ya conoce un poco a CVS y que quiera aprender sobre el control de versiones con Subversion.

La página web de Subversion es http://subversion.tigris.org.

Los comandos que aparecen precedidos de # deberán ser ejecutados por el administrador de la máquina ( root ), y los que estén precedidos de $ deberán ser ejecutados por el nuestro usuario ( en mi caso kikov ).

Necesitaremos las herramientas de línea de comandos ( el paquete subversion ) que si estamos en GNU/Debian podremos obtener así:

# apt-get install subversion
También necesitaremos si queremos usar Apache2 para publicar los repositorios

# apt-get install apache2-common

Y el módulo para Apache2 de subversion

# apt-get install libapache2-subversion

Un poco de teoría

Antes de empezar, comentar que Subversion sirve para gestionar un repositorio de archivos y sus distintas versiones. Un repositorio no es nada más que un sitio donde guardar ficheros. No nos importa cómo se guardan, sino cómo se accede a estos ficheros. Normalmente se usa una base de datos.

Pero la idea es que un repositorio es como un directorio, al que le puedes pedir los ficheros que tenía hace un mes, o hace 2 días. Es capaz de recuperar el estado de los mismos a partir de la base de datos.

Así, como usuario, lo importante es poder recuperar distintas versiones ( en especial las últimas ) y poder actualizar el repositorio con una versión nueva.

Realmente alguna de estas cosas se puede hacer con metainformación. Es decir, información sobre la propia información que está guardando el repositorio. Así, que aparte de los ficheros, el repositorio debe guardar cuando llegaron hasta él, por cuántas versiones distintas ha pasado, y este tipo de información que le permita cumplir su objetivo.

A diferencia de CVS, Subversion hace las revisiones globales del repositorio.

Esto quiere decir, que un cambio en un fichero no introduce un salto de versión únicamente en este fichero, sino en todo el repositorio ( que avanza una _revisión_ )

Manos a la obra


Vamos a realizar una serie de ejercicios a modo de ejemplo sobre el uso básico de SVN. Luego iremos incrementando el orden de dificultad hasta montar un servidor sencillo de SVN.

Lo primero que hay que hacer es crear nuestro repositorio. A tal efecto, podemos ir preparando el sistema para hacerlo de la forma correcta. No obstante si no tienes permisos de administración en esa máquina, sáltate hasta el punto siguiente.

# [ -d /var/lib/svn ] && mkdir -p /var/lib/svn
# chown -R root.src /var/lib/svn
# chmod 2775 /var/lib/svn


Hemos preparado la ruta /var/lib/svn para almacenar distintos repositorios svn. Añadamos a nuestro usuario al grupo src

# addgroup kikov src
Para que se hagan efectivos los cambios tenemos que hacer un login de nuevo.

Para confirmar que estamos en el grupo src, solo basta con poner groups y verificar que aparece el grupo src.

$ groups
kikov sys tty disk lp dialout fax cdrom sudo audio dip src video

Pasamos a crear el repositorio propiamente dicho. Si tenemos permiso en /var/lib/svn, podemos poner lo siguiente:

$ svnadmin create /var/lib/svn/pruebas
$ ls -l /var/lib/svn/pruebas
total 28
drwxr-sr-x 2 kikov src 4096 2004-05-12 16:28 conf
drwxr-sr-x 2 kikov src 4096 2004-05-12 16:28 dav
drwxr-sr-x 2 kikov src 4096 2004-05-12 16:28 db
-r--r--r-- 1 kikov src 2 2004-05-12 16:28 format
drwxr-sr-x 2 kikov src 4096 2004-05-12 16:28 hooks
drwxr-sr-x 2 kikov src 4096 2004-05-12 16:28 locks
-rw-r--r-- 1 kikov src 376 2004-05-12 16:28 README.txt


Si por el contrario no tenemos privilegios, podemos crearnos un directorio en nuestro HOME, así

$ mkdir -p /home/kikov/svnroot
$ svnadmin create /home/kikov/svnroot/pruebas
A partir de ahora, usaré uno de los dos repositorios para no duplicar esfuerzos. Pero si has elegido el otro, tendrás que cambiarlo en todos los comandos que aparezcan.

Una vez que está creado el repositorio, vamos a crear la primera copia.

$ mkdir -p /home/kikov/svn/pruebas
$ cd /home/kikov/svn/pruebas
$ echo "Mi primer fichero en SVN" > README.txt


Y vamos a trasladarla al repositorio

$ cd /home/kikov/svn/pruebas
$ svn import file:///var/lib/svn/pruebas -m"Version Inicial"
Adding README.txt

Committed revision 1.

NOTA: Recuerda substituir file:///var/lib/svn/pruebas por file:///home/kikov/svnroot/pruebas si has decidido finalmente poner el repositorio en tu HOME.

El comando import de svn, lo que hace es copiar todo el árbol de directorios actual desde el que nos encontramos, como primera versión del repositorio.

Con la opción -m, le hemos dado el mensaje de Log directamente. Si no usamos la opción -m, entonces se abrirá el editor por defecto del sistema y tendremos la oportunidad de escribir ahí. Si no se escribe nada, entonces subversion da la opción de abortar.

El subdirectorio /home/kikov/svn/pruebas no es una copia de trabajo del repositorio. De hecho, no sirve para nada más. Así, que podemos borrarlo sin temor, ya que su contenido se ha copiado al repositorio.

$ rm -rf /home/kikov/svn/pruebas

Vamos ahora a obtener nuestra Copia Local. Esto es de gran importancia, porque es el directorio de trabajo, desde donde se supone vamos a ir subiendo los cambios hacia el repositorio. Para ello se usa el comando checkout de svn.


$ cd /home/kikov/svn
$ svn checkout file:///var/lib/svn/pruebas
$ ls -l
total 4
drwxr-xr-x 3 kikov kikov 4096 2004-05-12 16:44 pruebas


Por cierto, también puedes querer copiarlo con otro nombre.


$ svn checkout file://var/lib/svn/pruebas pruebas2
$ ls -l
$ total 8
drwxr-xr-x 3 kikov kikov 4096 2004-05-12 16:44 pruebas
drwxr-xr-x 3 kikov kikov 4096 2004-05-12 16:44 pruebas2



Y dentro está nuestro fichero. Además de otras cosas ocultas. Si quieres verlas


$ ls -laR | grep svn
...


Vamos a añadirle un nuevo fichero:


$ cd /home/kikov/svn/pruebas
$ echo "Segundo fichero de pruebas" > README2.txt
$ svn add README2.txt
A README2.txt
$ svn commit -m"New File Added"
Adding README2.txt
Transmitting file data .
Committed revision 2.



Como se puede observar, una vez dentro de una copia local, NO es necesario indicarle la ruta al repositorio, pues ya la conoce. svn add realmente no añade el fichero al repositorio, simplemente lo marca para añadir. El que ejecuta la operación finalmente es el comando svn commit.

Advierta que ahora estamos en la revisión 2 del código.

Vamos a modificar un fichero de estos. Le añadadiremos una línea.


$ cd /home/kikov/svn/pruebas
$ echo "Esto es otra linea" >> README.txt

Y subimos los cambios

$ svn commit -m"Linea añadida"
Sending README.txt
Transmitting file data .
Committed revision 3.

Vamos a probar otra cosa interesante:

$ echo "Otra Nueva Linea" >> README.txt
svn diff
Index: README.txt
===================================================================
--- README.txt (revision 3)
+++ README.txt (working copy)
@@ -1,2 +1,3 @@
Mi primer fichero en SVN
Nueva Linea
+Otra Nueva Linea


Con este comando, svn diff podemos ver las diferencias entre el repositorio y nuestra copia local.

Mandémoslo al repositorio, porque ahora se pondrá la cosa algo más complicada

$ svn commit -m"Otra linea añadida"
Sending README.txt
Transmitting file data .
Committed revision 4.

Gestionando conflictos con Subversion


Ahora vamos a simular 2 personas accediendo al mismo repositorio. Para ello vamos a usar el otro directorio que creamos al principio. Si no lo tiene, ejecute el comando para obtenerlo.

Vamos a modificar un fichero en los dos repositorio y observar un conflicto.


Primero actualizaremos pruebas2 a la última versión:


$ cd /home/kikov/svn/pruebas2
$ svn update
U README.txt
A README2.txt
Updated to revision 4.



El comando svn update ( abreviado svn up ) actualiza una copia local con el repositorio, integrando los cambios que ha habido desde la última sincronización.

Ahora añadimos una linea en pruebas

$ cd /home/kikov/svn/pruebas
$ echo "Cuarta linea" >> README.txt

y otra en pruebas2 distinta

$ cd /home/kikov/svn/pruebas2
$ echo "Cuarta linea, pero modificada en pruebas2" >> README.txt

Hagamos un commit en la primera copia local

$ cd /home/kikov/svn/pruebas
$ svn ci -m"Mas líneas"
Sending README.txt
Transmitting file data .
Committed revision 5.

Ahora intentemos el commit desde la copia 2.

$ cd /home/kikov/svn/pruebas2
$ svn ci -m"Mas líneas en prueba2"
Sending README.txt
svn: Commit failed (details follow):
svn: Out of date: 'README.txt' in transaction '9'
svn: Your commit message was left in a temporary file:
svn: '/home/kikov/svn/pruebas2/svn-commit.tmp'


Nos dice que no estamos actualizados. Probemos a actualizar pruebas2 a la última revisión.

$ cd /home/kikov/svn/pruebas2
$ svn up
C README.txt
Updated to revision 5.

La C indica que hubo un conflicto!


Veamos el fichero

$ cd /home/kikov/svn/pruebas2
$ cat README.txt
Mi primer fichero en SVN
Nueva Linea
Otra Nueva Linea
<<<<<<< .mine
Cuarta linea, pero modificada en pruebas2
=======
Cuarta linea
>>>>>>> .r5


Lo solucionamos decidiendo con que versión nos quedamos, y ya podemos volver a hacer un commit.

También se creará en nuestro directorio sendos ficheros

README.txt.mine y README.txt.r5, aparte del mencionado svn-commit.tmp.

Este ha sido un repaso por los comandos más habituales de svn.

Entre otros podemos encontrar log.


$ cd /home/kikov/svn/pruebas
$ svn log README.txt
------------------------------------------------------------------------
r5 | kikov | 2004-05-12 17:26:30 +0200 (Wed, 12 May 2004) | 1 line

Mas líneas
------------------------------------------------------------------------
r4 | kikov | 2004-05-12 17:21:13 +0200 (Wed, 12 May 2004) | 1 line

Otra línea añadida
------------------------------------------------------------------------
r3 | kikov | 2004-05-12 16:58:39 +0200 (Wed, 12 May 2004) | 1 line

Linea añadida
------------------------------------------------------------------------
r1 | kikov | 2004-05-12 16:30:47 +0200 (Wed, 12 May 2004) | 1 line

Version Inicial
------------------------------------------------------------------------


Que también es bastante interesante.

Instalando Apache2 con Subversion (Instalando Subversion en Apache2)


Antes de nada, decir, que es algo arriesgado si no se conoce bien. Si no se hace viendo vamos a dar permiso de escritura con el usuario www-data.

Lo primero es la seguridad, así que voy a hablar un poco de ella antes.

A la hora de acceder a un repositorio vía Apache2, 2 sistemas de seguridad entran en juego. La autentificación y la autorización. La primera es estar seguro que QUIÉN es el que va a acceder. Es decir, identificar al usuario, mediante una contraseña o cualquier otro método. El segundo, es saber sí ese usuario PUEDE hacer lo que ha pedido.

La fase de autentificación, de existir, es anterior a la de autorización. Para la primera fase, existen multitud de módulos de Apache2 que cubren los requerimientos. Nosotros usaremos el más sencillo. Un fichero .htaccess.

El resto de los módulos se activa:

# a2enmod dav
# a2enmod dav-fs
# a2enmod svn
# a2enmod authz-svn

Para ello, vamos a crearnos un VirtualHost.

Yo, para mi máquina local, lo he llamado svn.kikov

/etc/apache2/sites-available/25dav


<VirtualHost 127.0.0.1:80>
  ServerName dav.kikov
  DAVLockDB /tmp/DAVLockSVN
  DocumentRoot /var/svnwww
  AssignUserID www-data src
  DirectoryIndex index.php

  php_flag engine on
  RewriteEngine on
  RewriteRule ^/svn$ /index.php [PT]
  RewriteRule ^/svn/$ /index.php [PT]
  RewriteRule ^/svn/index.html$ /index.php [PT]
  RewriteRule ^/index.htm$ /index.php [PT]
  RewriteRule ^/index.html$ /index.php [PT]
  <Location /svn>
    AuthType Basic
    AuthName "Subversion repository"
    AuthUserFile /var/lib/svnwww/svnusers
    Dav svn
    SVNParentPath /var/lib/svn
    SVNIndexXSLT /svnindex.xsl
    SVNAutoversioning on

    AuthzSVNAccessFile /var/lib/svnwww/svnaccess

    Require valid-user
  </Location>
</VirtualHost>


Para activarlo:

# ln -sf /etc/apache2/sites-available/25dav /etc/apache2/sites-enabled/25dav

Para más información de cómo configurar VirtualHosts, puedes mirar la documentación de apache en http://httpd.apache.org.


Con esta configuración, podemos tener una página principal con el listado de directorios, y con los 2 ficheros necesarios para la seguridad.


El primero de los ficheros (/var/lib/svnwww/svnusers) se puede crear y mantener con htpasswd


# htpasswd -c /var/lib/svnwww/svnusers
Para el segundo de los ficheros, encontrará buena documentación aquí:

http://svnbook.red-bean.com/svnbook/ch06s04.html#svn-ch-6-sect-4.4.2

En la configuración global de Apache2, deberíamos tener lo siguiente


NumServers 7
ChildPerUserID www-data.www-data 2
ChildPerUserID www-data.src 4


Y en /var/svn/www, unos ficheros aquí listados:

index.php svnindex.css svnindex.xsl

Los ficheros svnindex.css y svnindex.xsl, los podrás encontrar en la distribución de libapache2-svn

/var/www/apache2-default/svnindex.xsl
/var/www/apache2-default/svnindex.css

El otro fichero, lo puede arreglar a su gusto, y lo que hace es sacar una lista de los repositorios

index.php


<html>
 <head>
  <title>Subversion Repositories</title>
 </head>
 <body>

  <h2>Subversion Repositories</h2>
  <p><?php
   $svnparentpath = "/var/lib/svn";
   $svnparenturl = "/svn";

   $dh = opendir( $svnparentpath );
   if( $dh ) {
    while( $dir = readdir( $dh ) ) {
     $svndir = $svnparentpath . "/" . $dir;
     $svndbdir = $svndir . "/db";
      if( is_dir( $svndir ) && is_dir( $svndbdir ) ) {
       echo "<a href=\"" . $svnparenturl . "/" . $dir . "\">" .
           $dir . "</a><br />\n";
      }
     }
     closedir( $dh );
    }
   ?>
   </p>

 </body>
</html>


Los otros dos ficheros sirven para tener un navegador sencillo del repositorio cuando se navega a través de http://, con un navegador como Mozilla. ( Lo siento pero no va en Konqueror ).

Hemos usado la opción de Autoversioning, que nos permitirá la Autocreación de nuevas versiónes cuando insertemos algo desde un navegador Dav como Konqueror. Para usar la navegación Dav desde Konqueror es muy simple. En la barra de direcciones y gracias a los KIO escriba:

webdav://usuario@dav.kikov:/svn/pruebas

y déjese llevar ;).

También se puede usar un viewcvs para navegar por los repositorios SVN, y éste le permitirá ver diferencias entre versiones.

Por supuesto, podrá seguir accediendo a los repositorios normalmente, y ahora por vía Web también.

$ svn checkout http://dav.kikov/svn/pruebas