Professional Documents
Culture Documents
Plan de formaciones generales
Introducción a CVS
19 de Abril de 2010
Indice
1. SW libre para el control de versiones
2. Sistemas de control de versiones
3. Instalación
4. Configuración
5. Trabajar en proyectos
6. Resolución de conflictos
7. Tags y branches
SW libre para el control de versiones
Los sistemas de control de versiones han sido una
herramienta clave para los programadores del mundo del
software libre.
Han sido muchos los que han podido montar sus propios
servicios de control de versiones, desde grandes
instituciones educativas y económicas hasta pequeños
grupos de apasionados.
SW libre para el control de versiones
Esto ha sido posible a la disponibilidad del software libre.
El software libre garantiza las siguientes libertades:
Lib. 0: Libertad de usar el programa.
Lib. 1: Libertad de estudiar y modificar el programa.
Lib 2: La libertad de distribuir el programa con el prójimo.
Lib. 3: La libertad de realizar mejoras y liberarlas.
Sistema de control de versiones
Gestión de los cambios que se realizan sobre los
elementos de algún producto o configuración del mismo.
Un sistema de control de versiones debe proporcionar:
• Mecanismo de almacenaje de los elementos que deba
gestionar (ej. archivos, imágenes, documentación...)
• Posibilidad de modificar los elementos almacenados (ej.
modificaciones parciales, añadir, borrar, renombrar...)
• Registro histórico de las acciones realizadas con cada
elemento o conjunto de elementos (normalmente pudiendo
volver o extraer un estado anterior del producto)
Control de versiones centralizado
Todo el código se almacena en un repositorio centralizado.
Hay uno o varios responsables de todo el código.
Más fácil de administrar pero menos flexible.
Herramientas: CVS, Subversion...
Control de versiones distribuido
Cada usuario cuenta con su propio repositorio.
No es necesario decidir de forma centralizada.
Herramientas: Git, Mercurial...
CVS: Concurrent Versions System
Sistema de control de versiones centralizado.
Cuenta con arquitectura cliente – servidor.
Muy popular en el mundo del software libre.
Liberado bajo licencia GNU GPL
Más herramientas
Distribuídas Centralizadas
Aegis Git CVSNT
ArX GNU arch OpenCVS
Bazaar LibreSource Subversion (SVN)
Codeville Mercurial Vesta
Darcs Monotone FTPVCS
DCVS SVK
Fossil
Instalación en Ubuntu Linux 8.04 LTS
Instalamos los servicios CVS (cvs) y pserver (cvsd):
A continuación el sistema nos preguntará qué repositorios
utilizaremos:
Instalación en Ubuntu Linux 8.04 LTS
El repositorio es un lugar donde se guarda la copia
principal de todos los ficheros de los proyectos.
Es posible utilizar más de un repositorio.
Cada repositorio se guarda en un directorio.
Guardaremos los repositorios bajo /var/lib/cvsd
De esta forma la instalación estará terminada.
Creación de repositorios
Creamos el repositorio:
Lo utilizaremos sólo para esto y nadie podrá subir ficheros.
Creamos el usuario anonymous con una contraseña vacía:
Creamos el fichero writers vacío para que nadie suba nada:
En caso contrario el servicio SSH del servidor CVS nos
pediría la contraseña del usuario cada vez que
realizasemos alguna acción de CVS.
Creación de llaves SSH
En la máquina cliente, con la que vamos a trabajar contra
el servidor CVS, creamos las llaves SSH:
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/usuario/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/usuario/.ssh/id_rsa.
Your public key has been saved in /home/usuario/.ssh/id_rsa.pub.
The key fingerprint is:
62:28:3c:c5:56:c2:83:64:32:86:2a:2c:36:f3:57:93 usuario@maquina
Creación de llaves SSH
Esto crea dos llaves:
La llave pública: /home/usuario/.ssh/id_rsa.pub
La llave privada: /home/usuario/.ssh/id_rsa
Hay que copiar la llave pública en el servidor.
Copiamos el contenido de la llave pública del cliente en el
fichero de llaves autorizadas del servidor:
$ gedit /home/usuario/.bashrc
export CVS_RSH=ssh
export CVSROOT=:ext:cvsuser@localhost:/var/lib/cvsd/tresnaola
Configuración del cliente
La configuración se aplicará a partir de la próxima vez que
iniciemos sesión en el sistema o en el entorno gráfico.
En lugar de lo anterior también se puede ejecutar:
$ source /home/usuario/.bashrc
$ mkdir /home/usuario/tmp
$ cd /home/usuario/tmp
$ gedit colores.txt
$ gedit numeros.txt
Crear un proyecto
El contenido de los ficheros es el siguiente:
colores.txt numeros.txt
negro cero
marrón uno
rojo dos
naranja tres
amarillo cuatro
verde cinco
Crear un proyecto
Creamos el proyecto a partir del contenido del directorio:
Proyecto creado, eliminamos el directorio temporal.
$ cd
$ rm -rf /home/usuario/tmp
Trabajar en un proyecto
Creamos una carpeta de trabajo e importamos el proyecto:
$ mkdir /home/usuario/work
$ cd /home/usuario/work
$ cvs co cursocvs
Creará el directorio del proyecto en el directorio de trabajo.
$ ls
cursocvs
El cliente crea un directorio por proyecto importado.
¿Cómo importar con cada tipo de acceso?
Local:
Pserver (Sólo acceso anónimo)
Ext
Añadimos al fichero colores.txt las siguientes líneas:
azul
púrpura
gris
blanco
Comprobar modificaciones
Accedemos al directorio del proyecto:
$ cd /home/usuario/work/cursocvs
Comprobar modificaciones
Comprobamos el estado de todos los ficheros:
$ cvs status
cvs status: Examining .
===================================================================
File: colores.txt Status: Locally Modified
Working revision: 1.1.1.1
Repository revision: 1.1.1.1 /var/lib/cvsd/tresnaola/cursocvs/colores.txt,v
Commit Identifier: b7tW2aEIn58qj9vu
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)
===================================================================
File: numeros.txt Status: Up-to-date
Working revision: 1.1.1.1
Repository revision: 1.1.1.1 /var/lib/cvsd/tresnaola/cursocvs/numeros.txt,v
Commit Identifier: b7tW2aEIn58qj9vu
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)
Comprobar modificaciones
Comprobamos el estado de un solo fichero:
$ cvs diff
cvs diff: Diffing .
Index: colores.txt
===================================================================
RCS file: /var/lib/cvsd/tresnaola/cursocvs/colores.txt,v
retrieving revision 1.1.1.1
diff -r1.1.1.1 colores.txt
6a7,10
> azul
> púrpura
> gris
> blanco
Comprobar modificaciones
Comprobamos los cambios de un solo fichero:
Todos los cambios se guardan en un unico fichero .list
generado con cvs diff.
Es algo muy usual en el mundo del software libre.
Es una forma de colaborar en proyectos y envíar mejoras,
sobre todo cuando no podemos hacer un commit.
Diffs y parches
Un desarrollador genera un fichero diff.list con los cambios
realizados en el código:
Añadimos magenta al fichero colores.txt y lo enviamos:
Ver el mismo historial pero de un solo fichero:
Muestra la misma información que el anterior pero de un
solo fichero:
Si el fichero no ha sido envíado, no hay problema.
Simplemente se elimina y se actualiza la copia local.
Si el fichero ya está en el servidor, tampoco hay problema,
porque podemos hacer que el fichero vuelva atrás, a la
revisión anterior.
Deshacer cambios
Para devolver un fichero justo a la revisión anterior:
Esto ha aplicado los cambios en el colores.txt y sólo nos
quedaría envíarlo al servidor:
Crearemos el directorio fechas y dentro de él un fichero
que se llame dias.txt.
$ mkdir fechas
$ gedit fechas/dias.txt
Añadir nuevos ficheros y directorios
El contenido del fichero dias.txt es el siguiente:
lunes
martes
miércoles
jueves
viernes
sábado
domingo
Añadir nuevos ficheros y directorios
Y ahora añadimos los ficheros al control de versiones:
1. Renombrar el fichero en local
2. Eliminarlo del servidor
3. Añadir el fichero local renombrado al control de
versiones
4. Subir el nuevo fichero al servidor
Renombrar ficheros
Ejemplo:
$ mv documento.odt manual.odt
1. Crear el nuevo directorio
2. Añadirlo al control de versiones
3. Mover los ficheros de un directorio al otro
4. Eliminar el directorio anterior del control de versiones
5. Añadir el nuevo directorio al control de versiones
6. Aplicar los cambios en el servidor
Renombrar directorios
Ejemplo:
$ mv mkdir medidas
$ mv fechas/dias.txt medidas
$ cvs update -P
Ficheros binarios
CVS está diseñado para trabajar con ficheros de texto.
Guarda cada revisión como un conjunto de líneas
cambiadas, en lugar de guardar todo el fichero.
Gestiona los diferentes finales de línea de cada SO.
Puede añadir anotaciones automaticamente.
Ficheros binarios
Es posible que ocurran errores en CVS si le envíamos
ficheros binarios, como documentos ODT o PDF.
No podrán calcularse las diferencias entre revisiones.
En los ficheros binarios no existen los finales de línea como
tales, puede que CVS los interprete y produzca errores.
Si un fichero contiene secuencias parecidas a una keyword
de CVS, también pueden producirse errores.
Ficheros binarios
De todas formas CVS puede gestionar ficheros binarios, si
al añadir los ficheros al repositorio utilizamos la opción kb.
Por ejemplo:
Hay dos escenarios en los que puede ocurrir:
1. Antes de enviarlos al servidor (antes del commit)
2. Tras enviarlos al servidor (después del commit)
Marcar ficheros como binarios (Escen. 1)
Si hemos añadido un fichero binario al control de versiones
sin kb pero aún no lo hemos envíado al servidor, podemos
realizar lo siguiente:
1. Renombrarlo como fichero temporal
2. Quitarlo del control de versiones
3. Renombrar el fichero temporal al nombre original
4. Añadirlo al control de versiones con la opción kb
5. Envíarlo al servidor CVS
Marcar ficheros como binarios (Escen. 1)
Ejemplo:
1. Aplicar kb directamente en el fichero del servidor
2. Resetear los flags del fichero local
3. Copiar una versión íntegra del mismo documento desde
otra ubicación a esta.
4. Envíar los cambios al servidor.
Marcar ficheros como binarios (Escen. 2)
Ejemplo:
Se pueden utilizar para que al subir ficheros binarios al
repositorio este los marque con kb automaticamente.
cvswrappers
Se pueden definir de tres modos:
1. Dentro del fichero csvwrappers de directorio
CVSROOT del repositorio.
2. En un fichero .csvwrappers de la home del usuario.
3. Utilizando el parámetro W en la línea de comandos.
cvswrappers (Modo 1)
Todos los desarrolladores comparten la configuración.
Nos descargamos el CVSROOT y editamos el fichero
csvwrappers y subimos los cambios:
$ cvs co CVSROOT
$ cd CVSROOT
$ gedit cvswrappers
*.odt -k 'b'
*.pdf -ḱ 'b'
$ cvs commit -m “Convertir .odt y .pdf en binarios”
$ cd ..
$ cvs release -d CVSROOT
cvswrappers (Modo 2)
Utilizando este método cada desarrollador puede tener una
configuración distinta para tratar los archivos.
Creamos el fichero .cvswrappers en el directorio home del
usuario de la máquina local:
$ gedit /home/usuario/.csvwrappers
*.odt -k 'b'
*.pdf -ḱ 'b'
cvswrappers (Modo 3)
No es muy recomendable usar este método, es el más
complicado y hay que acordarse de utilizarlo.
Se utiliza junto a la orden import.
Se añade el parámtetro W para decirle qué ficheros tratar
como binarios:
$ cvs import -W "*.odt -k 'b'" -W "*.pdf -k 'b'" -m '' cursocvs cursocvs initial
cvswrappers
Se puede crear un documento .odt, subirlo y luego ver su
estado, para saber que se ha marcado como binario:
$ touch manual.odt
$ cvs add manual.odt
$ cvs commit -m "Añadido el manual"
$ cvs status manual.odt
$ cvs status manual.odt
===================================================================
File: manual.odt Status: Up-to-date
Por ejemplo sería interesante ignorar ficheros .class o .jar
derivadas de compilaciones de prueba del código fuente.
Esto se realizando utilizando los mismos patrones que en
los cvswrappers, pero esta vez en ficheros .cvsignore que
se pueden ubicar dentro de cada directorio del proyecto.
cvsignore
Los ficheros .cvsignore puede tenerlos cada desarrollador
en su copia de trabajo local, sin necesidad de que estén en
el servidor.
Lo más adecuado sería subir estos ficheros .cvsignore al
servidor, para que al descargarlos todos los
desarrolladores tengan la misma configuración en el
proyecto.
cvsignore
Por ejemplo, dentro del directorio cursocvs creamos un
fichero .class y otro .cvsignore:
$ touch Sinadura.class
$ gedit .cvsignore
*.class
*.jar
Y subimos .cvsignore cambios al servidor:
Por ejemplo sería interesante ignorar ficheros .class o .jar
derivadas de compilaciones de prueba del código fuente.
Trabajo en equipo
Cuando otros desarrolladores actualizan el código en el
servidor CVS, nuestra copia local queda desactualizada.
Sería posible comprobar esta situación si trabajásemos con
dos desarrolladores.
Se puede tener una copia del mismo proyecto en un
directorio diferente, simulando un segundo desarrollador.
Trabajo en equipo
Para importar un proyecto en un directorio local que tenga
un nombre distinto al directorio del proyecto en el servidor,
CVS ofrece el parámetro d en la orden checkout.
Vamos a utilizarlo para crear una nueva carpeta que se
llame cursoCVS. No es lo mismo cursocvs que
cursoCVS porque la mayoría de sistemas operativos
actuales diferencian entre mayúsculas y minúsculas.
$ cd cursoCVS
$ gedit numeros.txt
Envíamos la nueva versión al servidor:
Significa que la copia local necesita ser actualizada:
$ cvs update
cvs update: Updating .
P numeros.txt
Resolución de conflictos
Hemos visto como dos desarrolladores pueden trabajar
sobre un mismo proyecto de forma conjunta.
Ahora pasamos a ver los conflictos que se pueden generar.
Vamos a ver dos escenarios donde ambos desarrolladores
modifican y envían los cambios del mismo fichero:
1. Ambos desarrolladores modifican distintas líneas
2. Ambos desarrolladores modifican la misma línea
Resolución de conflictos (Escenario 1)
Vamos al directorio /home/usuario/work/cursocvs y
modificamos el fichero numeros.txt. Pondremos la línea
CERO en mayúsculas.
$ cd /home/usuario/work/cursocvs
$ gedit numeros.txt
CERO
uno
dos
tres
cuatro
...
Resolución de conflictos (Escenario 1)
Ahora vamos a /home/usuario/work/cursoCVS, donde
estamos simulando que somos otro desarrollador. En el
mismo fichero ponemos la línea siete en mayúsculas:
$ cd /home/usuario/work/cursoCVS
$ gedit numeros.txt
...
cuatro
cinco
seis
SIETE
Resolución de conflictos (Escenario 1)
Vamos al directorio /home/usuario/cursocvs y envíamos
los cambios al servidor CVS:
$ cd /home/usuario/work/cursocvs
$ cd /home/usuario/work/cursoCVS
Parece que hay algún tipo de error de actualización.
Veamos qué ocurre si actualizamos nuestra copia local:
$ cvs update
cvs update: Updating .
RCS file: /var/lib/cvsd/tresnaola/cursocvs/numeros.txt,v
retrieving revision 1.2
retrieving revision 1.3
Merging differences between 1.2 and 1.3 into numeros.txt
M numeros.txt
Resolución de conflictos (Escenario 1)
Durante la actualización vemos un mensaje adicional.
Dice que está combinando las diferencias entre versiones.
Veamos de qué se trata:
$ cat numeros.txt
CERO
uno
dos
...
seis
SIETE
Resolución de conflictos (Escenario 1)
Vemos que ha combinado el CERO del otro desarrollador
con el SIETE que hemos definido con el actual.
Esta combinación se realiza en nuestra copia local pero no
tiene ningún efecto en el servidor CVS.
Será necesario subir la nueva versión al servidor.
$ cd /home/usuario/work/cursocvs
$ cvs update
cvs update: Updating .
P numeros.txt
Resolución de conflictos (Escenario 2)
Vamos al directorio de trabajo local del primer desarrollador
y modificamos el fichero numeros.txt cambiando la línea
uno por ichi.
$ cd /home/usuario/work/cursocvs
$ gedit numeros.txt
CERO
ichi
dos
...
SIETE
Resolución de conflictos (Escenario 2)
Subimos los cambios al servidor:
$ cd /home/usuario/work/cursoCVS
$ gedit numeros.txt
CERO
bat
dos
...
SIETE
Resolución de conflictos (Escenario 2)
Subimos los cambios al servidor:
$ cvs update
cvs update: Updating .
RCS file: /var/lib/cvsd/tresnaola/cursocvs/numeros.txt,v
retrieving revision 1.4
retrieving revision 1.5
Merging differences between 1.4 and 1.5 into numeros.txt
rcsmerge: warning: conflicts during merge
cvs update: conflicts found in numeros.txt
C numeros.txt
Resolución de conflictos (Escenario 2)
«Si algo puede salir mal, saldrá mal.» (Ley de Murphy)
Ha habido errores durante la combinación de ficheros.
¿Hemos perdido todo nuestro trabajo? NO.
No es tan grave con CSV, los cambios realizados en local
se siguen manteniendo.
Resolución de conflictos (Escenario 2)
Habitualmente se dan este tipo de situaciones porque ha
habido algún tipo de malentendido entre desarrolladores.
El primer desarrollador pensaba que había que traducir la
línea uno al japonés (ichi), mientras que el otro pensaba
que había que traducirlo al euskera (bat).
Ha habido un error de comunicación. Aplicaremos nuestras
dotes detectivescas al más puro estilo Sherlock Holmes
para que ver cuál es el error, descubrir quién ha subido
la versión que está conflicto con la nuestra, y buscar una
solución con él y con el cliente.
Resolución de conflictos (Escenario 2)
Vamos a ver cuál es el error en el fichero numeros.txt:
$ cat numeros.txt
CERO
<<<<<<< numeros.txt
bat
=======
ichi
>>>>>>> 1.5
dos
tres
cuatro
cinco
seis
SIETE
Resolución de conflictos (Escenario 2)
Identificamos el cuerpo del delito.
Podemos ver que el conflicto es identificado entre los
símbolos <<<<<<< y >>>>>>>.
Primero vemos nuestro cambio (bat) y a continuación
vemos el cambio que está presente en el servidor (ichi).
Una pista a seguir: La versión del fichero es la 1.5 en el
servidor CVS.
Resolución de conflictos (Escenario 2)
¿Ha sido el mayordomo?
Sabemos que el fichero numeros.txt en su versión 1.5 del
servidor CVS está en conflicto con nuestra versión local.
Sabiendo esto podemos interrogar al servidor CVS para
hacerle cantar y que nos diga quién ha subido esta versión.
Esto se hace de la misma forma en la que se verifica el
historial de versiones de un fichero, con el parámetro log.
Resolución de conflictos (Escenario 2)
Interrogatorio
En la penúltima línea vemos que quién ha subido la versión
1.5 del fichero es el usuario cvsuser.
Ya tenemos la información necesaria:
1. Problema: (Utilizar ichi o bat en la línea uno)
2. Autor: El usuario cvsuser
Resolución de conflictos (Escenario 2)
«Elemental, mi querido Watson.» (¿Sherlock Holmes?)
En la penúltima línea vemos que quién ha subido la versión
1.5 del fichero es el usuario cvsuser (al final no era el
mayordomo).
Ya tenemos la información necesaria:
1. Problema: (Utilizar ichi o bat en la línea uno)
2. Autor: El usuario cvsuser
Resolución de conflictos (Escenario 2)
Nos ponemos en contacto con cvsuser y con el cliente, y
asunto solucionado. El cliente quería la línea uno en
japonés (ichi), y la línea dos en euskera (bi).
Modificamos el documento eliminando los marcadores de
conflicto de cvs <<<<<<< y >>>>>>> y corregimos su
contenido:
$ gedit numeros.txt
CERO
ichi
bi
...
Resolución de conflictos (Escenario 2)
Para terminar, subimos la nueva versión:
Y actualizamos la copia local del otro desarrollador:
$ cd /home/usuario/work/cursocvs
$ cvs update
cvs update: Updating .
P numeros.txt
Tags
Un tag no es más un nombre simbólico aplicado a ficheros.
Puede tener letras, números, guiones y guiones bajos.
Cada fichero aumenta su versión de forma independiente.
Relacionan cada revisión de cada fichero con un nombre.
Si creamos la tag REL_1, ahi podrían estar los ficheros
colores.txt rev1.5 y numeros.txt rev1.3.
Es posible aplicar más de una etiqueta a un fichero y rev.
Branch
Es un fork del desarrollo del código principal.
Puede haber distinas razones para hacer un branch:
1. Separar la preparación de releases
2. Corrección de bugs previo y posterior
3. Rama experimental
etc.
Branch Tags
Siempre que se crea una branch, a todos los ficheros se
les aplica una tag.
Esta tag identifica cuál es la versión en la que estaba el
fichero justo en el momento en el que se creó la branch.
Generar una branch
Para crear una branch, comprobamos que tenemos todos
los cambios envíados:
Y creamos la branch:
Y ya desde allí podemos trabajar como si estuvieramos en
la rama principal de desarrollo del proyecto.
Generar una release con tags
Para crear una release, comprobamos que tenemos el
repositorio actualizado o todos los cambios envíados:
$ cvs update
$ cvs commit -m ""
Desde ahora se podrá trabajar usando la tag:
Para ello vamos al directorio de la rama principal:
$ cd /home/usuario/work/cursocvs/
Y desde aquí llamamos al código de la branch:
http://oreilly.com/catalog/9780974514000
Bibliografía
zylk.net Wiki:
http://www.zylk.net/web/guest/web20/wiki//wiki/Main/CvsPrimerosPasos
¡Muchas gracias por su atención!
Joseba Martos
jmartos@zylk.net