Table of Contents
subversion svn control de versiones svnserve commit update merge
Subversion
Programa de cotrol de versiones.
Primeros pasos
En este ejemplo mostramos cómo poner en marcha 1 repositorio en subversion con 2 proyectos colgando del mismo.
1. Instalar subversion:
aptitude install subversion
2. Creamos el repositorio:
svnadmin create /home/repositorio_varios_proyectos/
3. Creamos la siguiente estructura para importar el primer proyecto:
/tmp/proyecto_1/trunk /tmp/proyecto_2/branches /tmp/proyecto_2/tags
4. Copiamos (si ya existen previamente) todos los ficheros del proyecto a importar al siguiente destino:
cp /ruta/proyecto /tmp/proyecto_1
5. Importamos el proyecto:
svn import /tmp/proyecto_1 file:///home/repositorio_varios_proyectos/proyecto_1 -m "Ingesta inicial"
6. Creamos el directorio donde bajar la copia de trabajo:
mkdir /home/proyecto_1
7. 'Descargamos' la última de ese proyecto del repositorio. Eso será nuestra copia de trabajo:
svn checkout file:///home/repositorio_varios_proyectos/proyecto_1/trunk
8. Tareas de ordenación
cd /home/proyecto_1/trunk mv * .. mv \.svn .. cd .. rm -fr trunk
9. Repetir los pasos 3-8 sustituyento 'proyecto_1' por 'proyecto_2'
Ciclo de trabajo
0. Descargar una copia de trabajo
- svn co
1. Actualizar la copia de trabajo
- svn update
2. Realizar cambios
- svn add
- svn delete
- svn copy
- svn move
3. Examinar cambios
- svn status
Para ver los cambios de la copia local respecto al repositorio:
- svn status –show-updates
- svn diff
4. (Opcional) revertir cambios realizados
- svn revert
5. Resolver conflictos (mezclar con otros cambios…)
- svn update
- svn resolve
6. Subir cambios al repositorio
- svn commit
Conocer la estructura del repositorio
ANTECEDENTES
Tenemos un repositorio de subversion con varios proyectos y no recordamos ni la ruta completa ni los nombres de los distintos proyectos albergados en el repositorio
SOLUCIÓN
1. Crear un directorio de prueba:
mkdir /tmp/prueba
2. Meterse en él
cd /tmp/prueba
3. Descargar el repositorio entero. En mi caso mediante el acceso desde la misma máquina que alberga el repositorio:
svn co file:///ruta/repositorio_varios_proyectos/
4. Para listar los proyectos:
ls -la /tmp/prueba/repositorio_varios_proyectos
Subversion y apache
Apache >=2.4.x y subversion >=1.8.x
http://svnbook.red-bean.com/en/1.8/svn.serverconfig.httpd.html
1. Instalar paquetes
sudo aptitude update; sudo aptitude install apache2 subversion libapache2-svn
2. Habilitar módulo de apache:
sudo a2enmod dav sudo a2enmod dav_lock sudo a2enmod dav_fs
3. Reiniciar apache
sudo service apache2 restart
4. Crear una config de apache:
sudo vim /etc/apache2/conf-available/svn.conf
Con el siguiente contenido:
<Location /svn> DAV svn # Automatically map any "/svn/foo" URL to repository /var/svn/foo SVNParentPath /var/svn </Location>
5. Ajustar permisos:
sudo chown -R www-data:root /var/svn
6. Cargar config de apache:
sudo a2enconf svn sudo service apache2 reload
7. Probar:
http://svn.example.com/svn/project_1
Deberia ir a:
/var/svn/project_1
Apache <=2.2.x y subversion <=1.7.x
http://svnbook.red-bean.com/en/1.4/svn.serverconfig.httpd.html
Prerrequisitos:
1. Apache 2
aptitude install apache2 subversion libapache2-svn
2. Habilitar módulo mod_dav de apache:
http://httpd.apache.org/docs/2.0/mod/mod_dav.html
Forma elegante:
a2enmod dav a2enmod dav_lock a2enmod dav_fs
No es necesario:
a2enmod dav_svn
Al estilo compadre:
ln -s /etc/apache2/mods-available/dav.load /etc/apache2/mods-enabled/ ln -s /etc/apache2/mods-available/dav_lock.load /etc/apache2/mods-enabled/ ln -s /etc/apache2/mods-available/dav_fs.load /etc/apache2/mods-enabled/ ln -s /etc/apache2/mods-available/dav_fs.conf /etc/apache2/mods-enabled/
Reiniciar apache
apache2ctl restart
Para comprobar que los módulos están cargados, un phpinfo();
3. Editar httpd.conf y añadirle:
<Location /mi_repositorio> DAV svn SVNPath /ruta/abosulta/al/repositorio </Location>
4. Reiniciar apache
apache2ctl restart
5. Cambiar los permisos para que el usuario www-data pueda acceder al repositorio de subversion, y así se puedan subir los cambios al repositorio:
chown -R www-data:root /ruta/abosulta/al/repositorio
EJEMPLO:
tenemos:
/home/usuario/repositorio_varios_proyectos
Y dentro de ese repositorio, 'proyecto_1'
/etc/apache2/httpd.conf así:
<Location /repositorio_varios_proyectos> DAV svn SVNPath /home/usuario/repositorio_varios_proyectos </Location>
Para descargarnos una copia local de ese proyecto_1:
svn checkout http://localhost/repositorio_varios_proyectos/proyecto_1
Proteger repositorio usando contraseña
Vamos a mostrar dos aproximaciones:
A) UN SOLO USUARIO
B) UN GRUPO DE USUARIOS POR PROYECTO
En ambos casos damos por hecho que la máquina solo contiene un repositorio de subversion, pues en caso contrario la directiva 'SVNPath' debería ser 'SVNParentPath'.
A) UN SOLO USUARIO
Para proteger el repositorio de subversion con un usuario y una contraseña:
1. Crear un usuario:
(Si no existe un fichero de contraseñas de apache)
sudo htpasswd -c /ruta/fichero/contrasenyas mi_usuario
(Si ya existe)
sudo htpasswd /ruta/fichero/contrasenyas mi_usuario
2. Teclear 2 veces la contraseña
3. Editar /etc/apache2/httpd.conf y dejarlo tal que así:
<Location /mi_repositorio> DAV svn SVNPath /ruta/abosulta/al/repositorio AuthType Basic AuthName "Usuario y contrasenya para el repositorio de subversion" AuthUserFile /ruta/fichero/contrasenyas Require user mi_usuario </Location>
4. (No sé si es necesario, supongo que si) apache2ctl restart
Para probar que funciona:
svn co --no-auth-cache --username mi_usuario http://localhost/mi_repositorio/proyecto_1 Reino de autentificación: <http://localhost> Usuario y contrasenya para el repositorio de subversion Clave de 'mi_usuario':
POSIBLES ERRORES
svn: El servidor envió un valor de devolución inesperado (500 Internal Server Error) en respuesta al requerimiento OPTIONS para 'http://localhost/mi_repositorio/proyecto_1'
Solución:
Verificar que la directiva AuthUserFile de /etc/apache2/httpd.conf coincide con la ruta al fichero de contraseñas que hemos usado para crear ese usuario (ver paso 1)
B) UN GRUPO DE USUARIOS POR PROYECTO
1. Creamos un par de usuarios:
(Si no existe un fichero de contraseñas de apache)
sudo htpasswd -c /ruta/fichero/contrasenyas usuario_1 sudo htpasswd /ruta/fichero/contrasenyas usuario_2
(Si ya existe)
sudo htpasswd /ruta/fichero/contrasenyas usuario_1 sudo htpasswd /ruta/fichero/contrasenyas usuario_2
2. Editar:
sudo vim /etc/apache2/httpd.conf
Y dejarlo tal que así:
ServerName localhost <Location /subversion> DAV svn SVNPath /home/repositorio_varios_proyectos # our access control policy AuthzSVNAccessFile /ruta/fichero/reglas_subversion # only authenticated users may access the repository Require valid-user # how to authenticate a user AuthType Basic AuthName "Repositorio subversion" AuthUserFile /ruta/fichero/contrasenyas </Location>
3. Grabar el archivo y salir
4. Crear el archivo de reglas:
sudo vim /ruta/fichero/reglas_subversion
Con el siguiente contenido:
[/proyecto_1] @administradores = rw [/proyecto_2] @usuarios = rw [groups] administradores = usuario_1 usuarios = usuario_1,usuario_2
5. Grabar y salir. NO es necesario reiniciar apache
6. Probar:
svn co --no-auth-cache --username usuario_1 http://servidor.mine.nu/subversion/proyecto_1 svn co --no-auth-cache --username usuario_1 http://servidor.mine.nu/subversion/proyecto_2 svn co --no-auth-cache --username usuario_2 http://servidor.mine.nu/subversion/proyecto_1 svn co --no-auth-cache --username usuario_2 http://servidor.mine.nu/subversion/proyecto_2
El tercer comando NO debería funcionar, pues 'usuario_2' no tiene acceso a 'proyecto_1'
Acceder a repositorio de subversion desde dentro de un proxy
ANTECEDENTES
Queremos acceder a un repositorio de Subversion que está configurado con Apache desde una máquina que está dentro de un cortafuegos.
Como toda conexión http, requerirá pasarle el usuario y la contraseña del proxy
SOLUCIÓN
1. nano /home/mi_usuario/.subversion/servers
2. Añadir las siguientes lineas:
http-proxy-host = mi_proxy http-proxy-port = puerto_proxy http-proxy-username = usuario_proxy http-proxy-password = contrasenya
3. Grabar y salir
4. Probar:
svn co http://url/repositorio/subversion/proyecto
Acceder a repositorio vía svn
0. Previo: mapear el puerto 3690 TCP del router (si lo hubiera) al servidor
(A partir de aquí como 'root')
1. Creamos el fichero de configuración:
mkdir /etc/subversion/conf nano /etc/subversion/conf/svnserve.conf
Con el siguiente contenido:
[general] password-db = contrasenyas realm = "Repositorio subversion vía svnserve" # No se permite la conexión de usuarios anónimos anon-access = none # Los usuarios autentificados pueden leer y escribir auth-access = write
2. Grabamos y salimos
3. Creamos el fichero de contraseñas:
nano /etc/subversion/conf/contrasenyas
Con el siguiente contenido:
[users] mi_usuario = contrasenya
4. Grabamos y salimos
5. Damos permisos:
chmod 600 /etc/subversion/conf/svnserve.conf /etc/subversion/conf/contrasenyas
6. Arrancamos el servidor:
svnserve -d --config-file=/etc/subversion/conf/svnserve.conf -r /home/repositorio_varios_proyectos&
7. Para acceder:
svn co --no-auth-cache --username mi_usuario svn://ip_maquina_repositorio/proyecto_1/trunk
POSIBLES ERRORES
- svn: La conexión de red se cerró inesperadamente
El servidor svnserve no está levantado y/o no está mapeado el puerto
Si se quieren añadir nuevos usuarios:
1. Editar el archivo de contraseñas:
nano /etc/subversion/conf/contrasenyas
2. Anyadir la nueva entrada debajo del bloque '[users]':
[users] mi_usuario = contrasenya mi_usuario_2 = contrasenya_2
3. Matar el proceso actual de svnsserve:
ps ax | grep svnserve 3038 ? Ss 0:00 svnserve -d --config-file=/etc/subversion/conf/svnserve.conf -r /mnt/disco_1/datos/repositorio_varios_proyectos kill -9 3038
4. Volver a arrancar snvserve:
svnserve -d --config-file=/etc/subversion/conf/svnserve.conf -r /mnt/disco_1/datos/repositorio_varios_proyectos&
Acceder a repositorio vía svn+ssh
No requiere tener levantado svnserve. Basta con:
svn co --no-auth-cache svn+ssh://usuario@ip_servidor_subversion/var/subversion/proyecto_1/trunk
Donde '/var/subversion' es la ruta completa al repositorio de subversion. Pedirá usuario y contraseña de una cuenta de usuario de la máquina donde esté ubicado el repositorio de subversion
Información del repositorio
ANTECEDENTES
Tenemos un repositorio de subversion con varios proyectos y no recordamos ni la ruta completa ni los nombres de los distintos proyectos albergados en el repositorio
SOLUCIÓN
1. Crear un directorio de prueba:
mkdir /tmp/prueba
2. Meterse en él
cd /tmp/prueba
3. Descargar el repositorio entero. En mi caso mediante el acceso desde la misma máquina que alberga el repositorio:
svn co file:///ruta/repositorio_varios_proyectos/
4. Para listar los proyectos:
ls -la /tmp/prueba/repositorio_varios_proyectos
ANTECEDENTES
Tenemos una copia local de un proyecto, pero no recordamos de qué repositorio depende
SOLUCIÓN
1. cd /ruta/copia_local
2.
svn info | grep URL URL: http://mi_url/subversion/proyecto_1/trunk
Ramas
NOTA Para que el comando 'svn merge' funcione, es necesario que cliente y servidor tengan la versión 1.5+
Normalmente los proyectos de subersion siguen el siguiente estándar:
/proyecto_1/trunk /proyecto_1/branches /proyecto_1/tags
Supongamos el siguiente esquema:
/proyecto_1/trunk/file.txt /proyecto_1/branches /proyecto_1/tags
Supongamos que siempre queremos que en '/trunk' esté una versión estable del proyecto, por ejemplo la '0.6'.
Ahora queremos empezar a trabajar en la versión 0.7, para que una vez finalizada, la reintegremos al tronco.
PROCEDIMIENTO
Crear una rama:
1. En el pc cliente:
svn copy http://mi_repositorio/proyecto_1/trunk \ http://mi_repositorio/proyecto_1/branches/version_0_7 \ -m "proyecto1 - creo rama branches/version_0_7"
2. (En el pc 'cliente') Descargamos una copia de trabajo del proyecto:
svn co http://mi_repositorio/proyecto_1/
3. Trabajo en file.txt:
cd branches/version_0_7 vim file.txt
4. Subo los cambios:
svn commit -m "proyecto1 - branches/version_0_7 cambio 1"
5. Sigo trabajando en file.txt:
cd branches/version_0_7 vim file.txt
6. Subo los cambios:
svn commit -m "proyecto1 - branches/version_0_7 cambio 2"
7. Si ahora quiero mezclar branches/version_0_7 → trunk tengo que buscar la revision en la que cree la rama:
svn log --verbose --stop-on-copy http://mi_repositorio/proyecto_1/branches/version_0_7
Tomar la ultima revision, por ejemplo supongamos que es la 23
8. Ir a trunk y ver la revision actual:
cd ../../trunk svn info
Supongamos que es la 25
9. Mezclar
svn merge -r 23:25 http://mi_repositorio/proyecto_1/branches/version_0_7
10. Actualizar repositorio
svn commit -m "proyecto1 - mezclado branches/version_0_7 -> trunk"
11. Comprobar los cambios
mkdir /tmp/aux2 cd /tmp/aux2 svn co http://mi_repositorio/proyecto_1/trunk cd trunk vim file.txt
Mezclando ramas
Supongamos el siguiente esquema:
http://mi_repositorio/proyecto_1/trunk http://mi_repositorio/proyecto_1/branches/version_1_0
Estamos trabajando en la version 1.0, pero nos consta que paralelamente se están resolviendo errores menores en la versión 'estable', alojada en 'trunk'. Periódicamente nos debemos traer a 'branches/version_1_0' los cambios que se hayan podido producir en 'trunk'. Para ello:
0. (Opcional) Configurarnos un editor externo para poder ver los cambios con mayor comodidad
1. Nos metemos en el interior de la copia de trabajo donde reside 'branches/version_1_0':
cd /directorio/local/branches/version_1_0
2. Lanzamos el comando para traernos los cambios desde 'trunk':
svn merge http://mi_repositorio/proyecto_1/trunk
Nos irán apareciendo una serie de ficheros que entran en conflicto. Sistemáticamente:
2.1 Editar el fichero: 'e' + 'enter'
Si hemos seguido el paso 0, se debería de haber abierto un editor externo, en el ejemplo 'scite' con el contenido. La sintaxis es básica (no es textual):
<<<<<<<< branches $V = $A + $C; ======== $V = $A + $C - $D; >>>>>>>> trunk
Debemos pues ver las dos versiones, la nuestra (entre '«««<' y '======') y la de 'trunk' (entre '=======' y '»»»'). Puede aparecer varias veces a lo largo del mismo fichero, una por cada cambio que subversion detecte.
Depuramos el código, grabamos y cerramos la ventana.
2.2 A la pregunta que nos hace: 'r' + 'enter'
Así el mismo ciclo hasta concluir con todos los cambios.
3. Subir los cambios al repositorio 'branches/version_1_0':
scn commit -m "Versión 1.0 actualizada con los cambios de trunk"
Editor externo
Para que en lugar de vim o nano nos abra otro editor:
(Con el usuario con el que se esté operando en la copia de trabajo)
1. Exportar la variable:
export SVN_EDITOR="/usr/bin/scite"
NOTA: como toda variable global, se vacía al cerrar sesión
Ignorar cambios en directorios
Cuando en symfony creamos un proyecto se crea una estructura de directorios, entre los cuales encontramos:
/cache /log
Cuando se ejecuta ese proyecto, es decir, las páginas web que contiene, el motor de symfony va escribiendo archivos en esos directorios.
Supongamos que nosotros NO queremos ni subir ni descargar esos archivos:
1. (Desde dentro de la copia de trabajo) Actualizamos por si las moscas:
svn update
2. Eliminamos de subversion los archivos contenidos en esos directorios:
svn remove cache/* svn remove log/*
3. Subimos los cambios al repositorio:
svn co -m "Borrados cache/ y log/"
4. Eliminamos de nuestra copia de trabajo esos archivos:
rm -fr cache/* log/*
5. Ignoramos esos directorios mediante el uso de propiedades:
svn propedit svn:ignore cache/
Se nos abrirá un editor de textos.
6. Tecleamos el contenido del archivo, que en este caso es todos los archivos:
7. Guardamos y salimos
Repetir los pasos 5-7 sustituyendo 'cache' por 'log'
8. Subimos los cambios al repositorio:
svn commit -m "Ignorados cache/ y log/"
Borrar un directorio del repositorio
1. (Como root)
svn delete file://ruta/repositorio/proyecto/trunk/dir_1
Copia de seguridad
svnadmin hotcopy /ruta/mi/repositorio /ruta/repositorio_copia_seguridad
Teóricamente después se puede mover/ruta/repositorio_copia_seguridad como un directorio más en otra máquina, y configurando su acceso:
- http://...
- svn:… Ya tenemos el mismo repositorio levantado Para exportar el repositorio (útil cuando hay conflictos de versiones): svnadmin dump /ruta/repositorio > volcado_repositorio.dbd Para importarlo: svnadmin create /ruta/nuevo_repositorio svnadmin load /ruta/nuevo_repositorio < volcado_repositorio.dbd ===== Errores ====== *svn: Error analizando parámetros *svn: Could not open the requested SVN filesystem *svn: Server sent unexpected return value (403 Forbidden) in response to OPTIONS request for 'http://peluca.mine.nu/subversion/facsimile' *svn: Se esperaba un formato de FS entre 1 y '3', se encontró '4' Se está intentando acceder a un repositorio de una versión de subversión posterior (1.6) a la instalada (1.5). Solución: 1. Desde una máquina con una versión de subversión igual a la del repositorio (1.6): svnadmin dump /ruta/repositorio > volcado_repositorio.dbd 2. Desde el servidor con la versión antigua (1.5) creamos un nuevo repositorio limpio: svnadmin create /ruta/nuevo_repositorio 3. Cargamos el volcado generado en el paso 1: svnadmin load /ruta/nuevo_repositorio < volcado_repositorio.dbd ===== Descargar un solo archivo ====== svn update http://repositorio_subversion/proyecto/mi_archivo.c ===== Listar revisiones ====== *Nota* puede requerir primero: svn update Y luego: svn log ===== Comprobar si existen versiones nuevas en el repositorio ====== <code> svn st -u –no-auth-cache –username=USER Authentication realm: <http://URL_REPOSITORY> xxx Repository Password for 'USER': * 225051 generic-ci/generic-service-check.sh * 225051 generic-ci/generic-service-remove.sh * file2.sh * 225051 . Status against revision: 234242 </code> * 225051 → existe una nueva version en el servidor ===== Merge inverso o revertir a una revision concreta ====== * *PROBLEMA* queremos eliminar las ultimas x revisiones de un proyecto 1. Listar las revisiones <code> cd /ruta/copia/local svn log ———————————————————————— r1132 | root | 2012-06-18 15:45:06 +0200 (Mon, 18 Jun 2012) | 1 line back without symlinks ———————————————————————— r1131 | usuario | 2012-06-18 15:07:16 +0200 (Mon, 18 Jun 2012) | 1 line puppet symlinks sudo ———————————————————————— r1130 | usuario | 2012-06-18 15:05:41 +0200 (Mon, 18 Jun 2012) | 1 line puppet symlinks ssh ———————————————————————— r1129 | usuario | 2012-06-18 15:04:50 +0200 (Mon, 18 Jun 2012) | 1 line puppet symlinks module puppet cont and snmp ———————————————————————— r1128 | usuario | 2012-06-18 15:03:26 +0200 (Mon, 18 Jun 2012) | 1 line puppet symlinks module puppet ———————————————————————— r1127 | usuario | 2012-06-18 14:58:34 +0200 (Mon, 18 Jun 2012) | 1 line puppet symlinks module ntp ———————————————————————— r1126 | usuario | 2012-06-18 14:52:25 +0200 (Mon, 18 Jun 2012) | 1 line puppet symlinks module nfs ———————————————————————— r1125 | usuario | 2012-06-18 14:46:01 +0200 (Mon, 18 Jun 2012) | 1 line puppet symlinks module apt ———————————————————————— r1124 | usuario | 2012-06-18 14:42:23 +0200 (Mon, 18 Jun 2012) | 1 line puppet symlinks test 3 ———————————————————————— r1123 | usuario | 2012-06-18 14:40:23 +0200 (Mon, 18 Jun 2012) | 1 line puppet symlinks test 2 ———————————————————————— r1122 | usuario | 2012-06-18 14:38:53 +0200 (Mon, 18 Jun 2012) | 1 line test symlinks puppet ———————————————————————— r1121 | root | 2012-06-18 14:25:24 +0200 (Mon, 18 Jun 2012) | 1 line Initial feed ———————————————————————— </code> 2. Queremos volver a la version inicial (r1121): sudo svn merge -r1132:1120 . 3. Hacemos el commit: svn commit -m 'revert to r1120' ===== Copiar directorio evitando .svn ====== sudo rsync -r –exclude=.svn /ruta/origen /ruta/destino