subversion svn control de versiones svnserve commit update merge
====== Subversion ======
Programa de cotrol de versiones.
http://svnbook.red-bean.com/nightly/en/index.html
===== 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:
DAV svn
# Automatically map any "/svn/foo" URL to repository /var/svn/foo
SVNParentPath /var/svn
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:
DAV svn
SVNPath /ruta/abosulta/al/repositorio
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í:
DAV svn
SVNPath /home/usuario/repositorio_varios_proyectos
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í:
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
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: 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
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
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
http://svnbook.red-bean.com/en/1.1/ch04s04.html
===== 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 [[subversion#editor_externo|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 ======
svn st -u --no-auth-cache --username=USER
Authentication realm: 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
* 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
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
------------------------------------------------------------------------
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