You are on page 1of 112

 Servicio TRESNAOLA

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.

Las  decisiones  importantes  las  deben  aprobar  los 


responsabels.

Herramientas: CVS, Subversion...
Control de versiones distribuido
Cada usuario cuenta con su propio repositorio.

No es necesario decidir de forma centralizada.

Los  repositorios  pueden  intercambiar  y  centralizar 


revisiones entre ellos.

Herramientas: Git, Mercurial...
CVS: Concurrent Versions System
Sistema de control de versiones centralizado.

Cuenta con arquitectura cliente – servidor.

Guarda  los  cambios  en  distintas  revisiones  y  mantiene  el 


registro de todos ellos.

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):

$ sudo aptitude install cvs 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

/var/lib/cvsd  es  una  jaula  chroot  geneada 


automaticamente durante el proceso de instalación.
Instalación en Ubuntu Linux 8.04 LTS
Al definir el directorio de un repositorio su nombre siempre 
comenzará con el símbolo barra    /

Si  definimos  más  de  un  repositorio  separaremos  sus 


nombres utilizando el símbolo dos puntos    :
Instalación en Ubuntu Linux 8.04 LTS
Definiremos un único repositorio llamado tresnaola.

De esta forma la instalación estará terminada.
Creación de repositorios
Creamos el repositorio:

$ sudo cvs -d /var/lib/cvsd/tresnaola init


Creación de repositorios
Creamos el grupo tresnaola para el repositorio:

$ sudo addgroup tresnaola

Definimos  el  usuario  cvsd  como  propietario  del  directorio 


cvsd y lo añadimos al grupo del mismo nombre:

$ sudo chgrp -R tresnaola /var/lib/cvsd/tresnaola


Formas de acceso
Local: Se accede al repositorio desde la misma máquina

Pserver:  Acceso  remoto.  Los  usuarios  son  independientes 


del sistema operativo. El cifrado de las contraseñas es débil 
y los paquetes se transportan en texto plano por la red.

Ext:  Acceso  remoto  seguro  vía  SSH.  Antiguamente  se 


utilizaba RSH. Los usuarios son los del sistema operativo. El 
cifrado  de  las  contraseñas  es  fuerte  (el  del  sistema 
operativo) y los paquetes se transportan cifrados por la red 
desde el momento de login (funcionalidad de SSH).
Usuario anónimo
El  acceso  mediante  pserver  es  adecuado  para  permitir  el 
acceso anónimo a terceros que quieran descargar el código.

Lo utilizaremos sólo para esto y nadie podrá subir ficheros.

Creamos el usuario anonymous con una contraseña vacía:

$ sudo cvsd-passwd /var/lib/cvsd/tresnaola/ anonymous

Creamos el fichero writers vacío para que nadie suba nada:

$ sudo touch /var/lib/cvsd/tresnaola/CVSROOT/writers


Creación de usuarios para el acceso Ext
Creamos  un  usuario  en  el  sistema.  Lo  añadimos  al  grupo 
cvsd,  estando  en  este  grupo,  tiene  permisos  sobre  el 
repositorio.

$ sudo useradd -d /home/cvsuser -s /bin/bash -m -G tresnaola cvsuser


$ sudo passwd cvsuser
Creación de llaves SSH
Crearemos llaves SSH sin passphrase para que podamos 
trabajar sobre el servidor CVS sin password.

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.

El  servidor  guarda  las  llaves  publicas  de  los  usuarios 


autorizados en el fichero ~/.ssh/authorized_keys
Creación de llaves SSH
Creamos  el  directorio  .ssh  en  el  servidor  CVS  (Es  posible 
que exista, en ese caso no ocurrirá nada):

$ ssh cvsuser@localhost mkdir -p .ssh

Copiamos el contenido de la llave pública del cliente en el 
fichero de llaves autorizadas del servidor:

$ cat /home/usuario/.ssh/id_rsa.pub | ssh cvsuser@localhost 'cat >> .ssh/authorized_keys'


Configuración del cliente
Podemos configurar nuestro cliente GNU/Linux para que al 
usar  el  cliente  cvs  no  tengamos  que  definir  ni  forma  de 
acceso, ni usuario, ni servidor, ni repositorio.

Definimos  todos  los  parámetros  en  el  fichero  .bashrc  del 


directorio home de nuestro usuario:

$ 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.

Si  queremos  que  la  configuración  sea  válida  al  momento, 


podemos abrir una terminal y ejecutar:
$ export CVS_RSH=ssh
$ export CVSROOT=:ext:cvsuser@localhost:/var/lib/cvsd/tresnaola

En lugar de lo anterior también se puede ejecutar:
$ source /home/usuario/.bashrc

Hasta  reinicar  la  sesión,  la  configuración  sólo  será  válida 


en la terminal donde hemos ejecutado los comando.
Crear un proyecto
Un  nuevo  proyecto  se  crea  a  partir  de  un  directorio  local 
que contiene los ficheros que albergará el proyecto.

Creamos  un  directorio  temporal  (tmp)  y  dos  ficheros  de 


ejemplo (colores.txt y numeros.txt) para crear el proyecto.

$ 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:

$ cvs import -m "Inicial" cursocvs cursocvs initial


N cursocvs/numeros.txt
N cursocvs/colores.txt

No conflicts created by this import

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:

$ cvs -d /var/lib/cvsd/tresnaola co cursocvs

Pserver (Sólo acceso anónimo)

$ cvs -d :pserver:anonymous@localhost:/cvsroot co cursocvs

Ext

$ cvs -d :ext:cvsuser@localhost:/var/lib/cvsd/tresnaola co cursocvs


Comprobar modificaciones
CVS  ofrece  distinas  herramientas  para  comprobar  los 
cambios  que  han  sufrido  los  ficheros  en  comparación  con 
las  versiones  del  servidorCVS.  Lo  comprobamos   
modificando un fichero.

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 status colores.txt


===================================================================
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)
Comprobar modificaciones
Comprobamos los cambios de todos los ficheros:

$ 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:

$ cvs diff colores.txt


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
Vemos los cambios de un solo fichero en dos columnas.
$ cvs diff --side-by-side colores.txt
Index: colores.txt
===================================================================
RCS file: /var/lib/cvsd/tresnaola/cursocvs/colores.txt,v
retrieving revision 1.1.1.1
diff --side-by-side -r1.1.1.1 colores.txt
negro negro
marrón marrón
rojo rojo
naranja naranja
amarillo amarillo
verde verde
> azul
> púrpura
> gris
> blanco
Diffs y parches
Cuando  trabajamos  con  código  fuente  en  CVS,  podemos 
reflejar  un  listado  de  todos  los  cambios  realizados  en  el 
repositorio.

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:

$ cvs diff -u > diff.list

Se  le  envía  el  fichero  diff.list  al  responsable  del 


mantenimiento del código, y este simplementa hará:

$ patch -p 0 < diff.list


Diffs y parches
Un ejemplo de generación de diffs sería el siguiente:

$ cvs diff colores.txt


Envíar modificaciones
Enviamos al servidor CVS los cambios realizados:

$ cvs commit -m "4 colores más"


cvs commit: Examining .
/var/lib/cvsd/tresnaola/cursocvs/colores.txt,v <-- colores.txt
new revision: 1.2; previous revision: 1.1
Envíar modificaciones
Aún  si  hay  cambios  en  muchos  ficheros,  es  posible 
seleccionar qué ficheros deseamos subir.

Añadimos magenta al fichero colores.txt y lo enviamos:

$ cvs commit -m "Añadido magenta" colores.txt


/var/lib/cvsd/tresnaola/cursocvs/colores.txt,v <-- colores.txt
new revision: 1.3; previous revision: 1.2
Historial de los ficheros
Vemos el historial de versiones de todos los ficheros:
$ cvs log
cvs log: Logging .
RCS file: /var/lib/cvsd/tresnaola/cursocvs/colores.txt,v
Working file: colores.txt
...
total revisions: 4; selected revisions: 4
description:
----------------------------
revision 1.3
date: 2010-04-16 15:44:33 +0200; author: usuario; state: Exp; lines: +1 -0; commitid:
2Xc17z7JpRKlz9vu;
Añadido magenta
----------------------------
revision 1.2
...
=============================================================================
RCS file: /var/lib/cvsd/tresnaola/cursocvs/numeros.txt,v
Working file: numeros.txt
...
Historial de los ficheros
Vemos el historial de versiones de un solo fichero:
$ cvs log colores.txt
RCS file: /var/lib/cvsd/tresnaola/cursocvs/colores.txt,v
Working file: colores.txt
...
total revisions: 4; selected revisions: 4
description:
----------------------------
revision 1.3
date: 2010-04-16 15:44:33 +0200; author: usuario; state: Exp; lines: +1 -0; commitid:
2Xc17z7JpRKlz9vu;
Añadido magenta
----------------------------
revision 1.2
date: 2010-04-16 15:37:35 +0200; author: usuario; state: Exp; lines: +4 -0; commitid:
7VRGx9iclKzXw9vu;
4 colores más
----------------------------
revision 1.1
...
Más formas de ver el historial
Ver el historial desde hace dos días hasta hoy:
$ cvs log -d "2 days ago" -d today

Ver el mismo historial pero de un solo fichero:

$ cvs log -d "2 days ago" -d today colores.txt


Más formas de ver el historial
Ver el contenido de un fichero línea a línea, en cada línea 
se  muestra  la  última  revisión  que  la  cambió,  el  autor  y  la 
fecha del cambio:
$ cvs ann

Muestra  la  misma  información  que  el  anterior  pero  de  un 
solo fichero:

$ cvs ann colores.txt


Deshacer cambios
Es  posible  que  algún  desarrollador  envíe  al  servidor  CVS 
ficheros  con  código  fuente  incorrecto  o  que  no  tienen 
relación con el proyecto.

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:

$ cvs update -j1.3 -j1.2 colores.txt

En  este  ejemplo  se  ha  utilizado  el  fichero  colores.txt, 


hemos  puesto  primero  su  última  versión  y  después  la 
revisión anterior, a donde queremos volver.

Esto  ha  aplicado  los  cambios  en  el  colores.txt  y  sólo  nos 
quedaría envíarlo al servidor:

$ cvs commit -m "Revertido: Sin magenta" colores.txt


Añadir nuevos ficheros y directorios
Durante  el  desarrollo  de  un  proyecto,  se  crean  nuevos 
ficheros que necesitamos añadir al control de versiones.

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:

$ cvs add fechas


? fechas/dias.txt
Directory /var/lib/cvsd/tresnaola/cursocvs/fechas added
to the repository

$ cvs add fechas/dias.txt


cvs add: scheduling file `fechas/dias.txt' for addition
cvs add: use `cvs commit' to add this file permanently
Añadir nuevos ficheros y directorios
Finalmente  debemos  hacer  un  commit  para  que  los 
cambios tengan efecto en el servidor CVS:

$ cvs commit -m "Añadidos fechas y fechas/dias.txt"


cvs commit: Examining .
cvs commit: Examining fechas
/var/lib/cvsd/tresnaola/cursocvs/fechas/dias.txt,v <-- fechas/dias.txt
initial revision: 1.1
Renombrar ficheros
Para  renombrar  un  fichero  se  realiza  el  siguiente 
procedimiento:

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

$ cvs remove documento.odt

cvs remove: scheduling `documento.odt' for removal


cvs remove: use `cvs commit' to remove this file permanently

$ cvs add manual.odt

cvs add: scheduling file `manual.odt' for addition


cvs add: use `cvs commit' to add this file permanently

$ cvs commit -m "Renombrado documento.odt a manual.odt"


Renombrar directorios
Para  renombrar  un  directorio  se  realiza  el  siguiente 
procedimiento:

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

$ cvs add medidas

$ mv fechas/dias.txt medidas

$ cvs remove fechas/dias.txt

$ cvs add medidas/dias.txt

$ cvs commit -m "Renombrado documento.odt a manual.odt"

$ 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:

$ cvs add -kb documento.odt


Marcar ficheros como binarios
Al tener que añadirlos de una forma específica, es posible 
que alguna vez olvidemos añadir la opción ­kb.

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:

$ cvs add documento.odt


cvs add: scheduling file `documento.odt' for addition
cvs add: use `cvs commit' to add this file permanently
$ mv documento.odt tmp.odt
$ cvs remove documento.odt
cvs remove: removed `documento.odt'
$ mv tmp.odt documento.odt
$ cvs add -kb documento.odt
cvs add: scheduling file `documento.odt' for addition
cvs add: use `cvs commit' to add this file permanently
$ cvs commit -m "Añadido el nuevo documento"
Marcar ficheros como binarios (Escen. 2)
Si hemos añadido un fichero binario al control de versiones 
sin ­kb y además lo hemos envíado al servidor, podemos 
realizar lo siguiente:

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:

$ cvs admin -kb documento.odt


RCS file: /var/lib/cvsd/tresnaola/cursocvs/documento.odt,v
done
$ cvs update -A documento.odt
U doc.odt
$ cp /home/usuario/docs/documento.odt .
$ cvs commit -m "Marcado como binario -kb"
cvs commit: Examining .
cvs commit: Examining fechas
cvswrappers
Permiten definir características a los ficheros definiendo un 
patrón sobre el que se buscan coincidencias en el nombre.

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

Working revision: 1.1


...
Sticky Options: -kb
cvsignore
De la misma forma que hay ficheros binarios que nos 
interesa guardar en el control de versiones, como por 
ejemplo documentación en .odt y en .doc, también hay 
ficheros que nos interesa ignorar.

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:

$ cvs commit -m "Añadido el .cvsignore"


cvsignore
De la misma forma que hay ficheros binarios que nos 
interesa guardar en el control de versiones, como por 
ejemplo documentación en .odt y en .doc, también hay 
ficheros que nos interesa ignorar.

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.

$ cvs co -d cursoCVS cursocvs


cvs checkout: Updating cursoCVS
U cursoCVS/colores.txt
U cursoCVS/numeros.txt
Trabajo en equipo
Ahora iremos al directorio cursoCVS, y añadiremos las 
líneas seis y siete en el fichero numeros.txt

$ cd cursoCVS
$ gedit numeros.txt

Envíamos la nueva versión al servidor:

$ cvs commit -m "Añadidos seis y siete"


Trabajo en equipo
Volvemos a /home/usuario/work/cursocvs y vemos el 
estado actual del fichero numeros.txt:

$ cvs status numeros.txt


===================================================================
File: numeros.txt Status: Needs Patch

Working revision: 1.1.1.1


Repository revision: 1.2
/var/lib/cvsd/tresnaola/cursocvs/numeros.txt,v
Commit Identifier: KH2eELyZFnOb1bvu
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)
Actualizar el repositorio
Vemos el mensaje Status: Needs Patch.

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

$ cvs commit -m "Cero en mayúsculas"


cvs commit: Examining .
/var/lib/cvsd/tresnaola/cursocvs/numeros.txt,v <-- numeros.txt
new revision: 1.3; previous revision: 1.2
Resolución de conflictos (Escenario 1)
A continuación hacemos lo mismo en el directorio 
/home/usuario/cursoCVS:

$ cd /home/usuario/work/cursoCVS

$ cvs commit -m "Siete en mayúsculas"


cvs commit: Examining .
cvs commit: Up-to-date check failed for 'numeros.txt'
cvs [commit aborted]: correct above errors first!
Resolución de conflictos (Escenario 1)
¡OH NO! ¡Errores!

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.

$ cvs commit -m "Siete en mayúsculas"


cvs commit: Examining .
/var/lib/cvsd/tresnaola/cursocvs/numeros.txt,v <-- numeros.txt
new revision: 1.4; previous revision: 1.3
Resolución de conflictos (Escenario 1)
Ahora el otro desarrollador actualiza la copia local para 
seguir trabajando en el proyecto:

$ 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:

$ cvs commit -m "Traducido uno al japonés"


cvs commit: Examining .
/var/lib/cvsd/tresnaola/cursocvs/numeros.txt,v <-- numeros.txt
new revision: 1.5; previous revision: 1.4
Resolución de conflictos (Escenario 2)
Vamos al directorio de trabajo local donde simulamos el 
segundo desarrollador y modificamos el fichero numeros.txt 
cambiando la línea uno por bat.

$ cd /home/usuario/work/cursoCVS

$ gedit numeros.txt
CERO
bat
dos
...
SIETE
Resolución de conflictos (Escenario 2)
Subimos los cambios al servidor:

$ cvs commit -m "Traducido uno al euskera"


cvs commit: Examining .
cvs commit: Up-to-date check failed for `numeros.txt'
cvs [commit aborted]: correct above errors first!
Resolución de conflictos (Escenario 2)
Vemos que se repite la misma situación que en el 
escenario 1, así que actualizamos nuestra copia local:

$ 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

$ cvs log -r1.5 numeros.txt

RCS file: /var/lib/cvsd/tresnaola/cursocvs/numeros.txt,v


Working file: numeros.txt
head: 1.5
...
keyword substitution: kv
total revisions: 6; selected revisions: 1
description:
----------------------------
revision 1.5
date: 2010-04-16 16:40:12 +0200; author: cvsuser; state: Exp; lines: +1 -1; commitid: hJmARjkFkfRJJrvu;
Traducido uno al japonés
=============================================================================
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.

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:

$ cvs commit -m "uno en japones y dos en euskera"


cvs commit: Examining .
/var/lib/cvsd/tresnaola/cursocvs/numeros.txt,v <-- numeros.txt
new revision: 1.6; previous revision: 1.5

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:

$ cvs commit -m ""

Y creamos la branch:

$ cvs rtag -b RB_1_0


Trabajar con una branch
Para trabajar con una branch, simplemente tenemos que 
importarla a otro directorio de trabajo:

$ cvs co -r RB_1_0 -d rb1.0 cursocvs

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 ""

$ cvs tag REL_1_0

Desde ahora se podrá trabajar usando la tag:

$ cvs co REL_1_0 -d rel10 cursocvs


Combinar una branch con la rama principal
Cuando el desarrollo de una branch está suficientemente 
maduro, lo combinamos con la rama principal.

Para ello vamos al directorio de la rama principal:

$ cd /home/usuario/work/cursocvs/

Y desde aquí llamamos al código de la branch:

$ cvs update -j RB_1_0


Bibliografía
Pragmatic Version Control Using CVS

http://oreilly.com/catalog/9780974514000
Bibliografía
zylk.net Wiki:

http://www.zylk.net/web/guest/web­2­0/wiki/­/wiki/Main/CvsPrimerosPasos 
¡Muchas gracias por su atención!

Joseba Martos
jmartos@zylk.net