Este breve documento es una guía para manejar subversion tomando como base los conocimientos aprendidos usando cvs.
A primera vista subversion parece una implementación mejor realizada que su antecesor cvs en ciertos detalles que dan mayor juego y son más comodos de realizar.
Página del proyecto subversion: http://subversion.tigris.org/.
Version Control with Subversion: http://svnbook.red-bean.com/.
El comando svn tiene casi los mismos comandos que su homólogo cvs así que los ire exponiendo con un ejemplo.
Lo primero para empezar a trabajar es crear el repositorio principal donde se almecenará todo el proyecto.
dalamar:~ $ mkdir /home/chernando/svn
dalamar:~ $ svnadmin create /home/chernando/svn
Con esto hemos creado los archivos de control para manejar el repositorio. Más adelante comentaré algunas opciones de configuración.
Debido al sistema de branches y tags que utiliza subversion es recomendable seguir el siguiente patrón a la hora de crear proyectos:
/
/trunk
/branches
/tags
En el caso de querer de manejar varios proyectos en el mismo repositorio la cosa quedaría así:
/
/proyecto1
/trunk
/braches
/tags
/proyecto2
/trunk
/braches
/tags
De esta manera el trabajo de desarrollo principal se basará en el directorio trunk de cada proyecto dejando braches para manejar las ramas y tags para marcar las etiquetas.
Una vez creado el esquema de directorios utilizaremos el comando svn import RUTA REPOSITORIO. Veamos el ejemplo:
crysania:~ $ mkdir -p project/trunk
crysania:~ $ mkdir project/braches
crysania:~ $ mkdir project/tags
# Ahora importaremos el proyecto
crysania:~ $ svn import . svn+ssh://dalamar.shoikan.net/home/chernando/svn \
--message "Esquema inicial de directorios"
Podríamos haber copiado todo nuestro código de trabajo al directorio project/trunk antes de realizar el import sin embargo lo he dejado para el siguiente apartado.
Para obtener un módulo de trabajo utilizaremos el comando svn checkout REPOSITORIO/MODULO DIRECTORIO. Vamos a bajar el trunk para poder luego incluir los ficheros.
crysania:~ $ svn checkout svn+ssh://dalamar.shoikan.net/home/chernando/svn/trunk web
Checked out revision 1.
crysania:~ $ ls -a web
. .. .svn
El comando svn add es mucho más cómodo que en la versión cvs para verlo vamos a añadir todo el código del proyecto de la sección anterior de una pasada:
# Copiamos los ficheros que vamos a añadir al repositorio
crysania:~/web $ cp -r ~/trabajo/web/* .
# Utilizamos svn add para añadir todos los directorios y sus ficheros
crysania:~/web $ svn add *
A art
A art/apache
A art/apache/index.html
A art/xinerama
A (bin) art/xinerama/xinerama.jpg
...
# Como podemos ver, marca automáticamente los binarios y en ningún momento
# necesitamos conectarnos con el repositorio.
También podemos crear un directorio mediante svn mkdir DIRECTORIO y luego añadir los ficheros con svn add FICHERO:
crysania:~/web $ svn mkdir test
A test
crysania:~/web $ cd test
crysania:~/web/test $ touch test1
crysania:~/web/test $ svn add test1
A test1
Para ello usamos svn commit {FICHERO}* al que podemos añadir un comentario mediante la opción "--message" o nos abrirá un editor para comentar nuestros cambios.
crysania:~/web $ svn commit --message "Version inicial"
Adding art
Adding art/apache
Adding art/apache/index.html
Adding art/irc
Adding art/irc/1459
# [...]
Transmitting file data ................................
Committed revision 2.
crysania:~/web $
Para ello simplemente haremos svn update (exactamente igual que en cvs):
# He borrado manualmente el index.html para forzar su actualizacion
crysania:~/web $ svn update
U art/apache/index.html
Updated to revision 2.
Con svn [delete|del|remove|rm] {FICHERO}* podemos eliminar fácilmente ficheros o directorios y sus ficheros. Con svn [move|mv|rename|ren] ORIG DEST podemos renombrar cómodamente y además mantendrá el historial antes de su renombramiento (cosa que no ocurría con cvs).
# Primero renombrar test a basura
crysania:~/web $ svn mv test/ basura
A basura
D test/test1
D test
crysania:~/web $ svn commit -m "Movemos test a basura"
Adding basura
Deleting test
Committed revision 4.
crysania:~/web $ ls basura/
test1
crysania:~/web $
# Borremos ahora basura
crysania:~/web $ svn rm basura
D basura/test1
D basura
crysania:~/web $ svn commit -m "Fuera basura"
Deleting basura
Committed revision 5.
Veamos ahora como manejar los cambios y los problemas que surgen.
Normalmente cuando actualizamos un fichero a nuestra copia local solemos obtener el siguente resultado:
crysania:~/web $ svn update
U art/apache/index.html
Updated to revision 2.
Sin embargo si estamos trabajando sobre una version desactualizada del fichero, es decir se han realizado cambios en el repositorio, pueden ocurrir dos cosas.
Que las modificaciones sean diferentes por lo tanto no hay que hacer nada ya que svn se encarga de mezclar ambas versiones:
crysania:~/web $ svn update
G art/apache/index.html
Updated to revision 3.
O bien que las modificaciones sean en la misma region con lo que no se podran mezclar ambas: conflicto. En este caso svn generara tres archivos para manejar el conflicto:
crysania:~/web/art/apache $ svn update
C index.html
Updated to revision 4.
# Tenemos un conflicto en este fichero y svn genera:
crysania:~/web/art/apache $ ls -1 index.html.*
index.htm.mine
index.htm.r3
index.htm.r4
Siendo: .mine la version con la que estamos trabajando, .r3 la version que habia en el repositorio sobre la que estabamos trabajando y .r4 la version actual del repositorio. Ademas en index.html tendremos marcados los conflictos de la misma manera que los teniamos en cvs.
Se procede a corregir las regiones que esten en conflicto en el fichero base y se utiliza svn resolved FICHERO:
crysania:~/web/art/apache $ svn resolved index.html
Resolved conflicted state of 'acmfi.htm'
# Una vez resuelto el conflicto se eliminan los ficheros axuliares:
crysania:~/web/art/apache $ ls index.html.*
ls: index.html.*: No existe el fichero o el directorio
# No olvidarse de mandar los cambios
crysania:~/web/art/apache $ svn commit index.html \
-m 'Cambios en la organizacion'
Sending index.html
Transmitting file data .
Committed revision 5.
Otra de las comodidades de svn se aprecia en la realizacion de parches y en la revision del historial ya que para ambos casos no es necesario conectarse con el repositorio.
Para obtener los cambios realizados en nuestra copia local utilizaremos svn diff {FICHERO}* que nos da una salida valida para enviar parches (ademas de comprobar los cambios antes de enviarlos al repositorio).
crysania:~/web/art/apache $ svn diff index.html
Index: index.html
===================================================================
--- index.html (revision 4)
+++ index.html (working copy)
@@ -1,3 +1,4 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="es" xml:lang="es">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
Para revisar el historial (todos esos sarcasmos que se suelen utilizar en los --message de los commit) simplemente utilizar el comando svn log {FICHERO}*.