Servicio TRESNAOLAPlan de formaciones generales
Introducción a CVS19 de Abril de 2010
Indice
1. SW libre para el control de versiones2. Sistemas de control de versiones3. Instalación4. Configuración5. Trabajar en proyectos6. Resolución de conflictos7. Tags y branches
SW libre para el control de versionesLos 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 versionesEsto 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 versionesGestió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 centralizadoTodo 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 distribuidoCada 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 SystemSistema 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
AegisArXBazaarCodevilleDarcsDCVSFossil
GitGNU archLibreSourceMercurialMonotoneSVK
DistribuídasCVSNTOpenCVSSubversion (SVN)VestaFTPVCS
Centralizadas
Instalación en Ubuntu Linux 8.04 LTSInstalamos 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 LTSEl 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 LTSAl 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 LTSDefiniremos un único repositorio llamado tresnaola.
De esta forma la instalación estará terminada.
Creación de repositoriosCreamos el repositorio:
$ sudo cvs -d /var/lib/cvsd/tresnaola init
Creación de repositoriosCreamos 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 accesoLocal: 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ónimoEl 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 ExtCreamos 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 SSHCrearemos 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 SSHEn la máquina cliente, con la que vamos a trabajar contra el servidor CVS, creamos las llaves SSH:
$ ssh-keygen -t rsaGenerating 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 SSHEsto 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 SSHCreamos 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 clientePodemos 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=sshexport CVSROOT=:ext:cvsuser@localhost:/var/lib/cvsd/tresnaola
Configuración del clienteLa 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 proyectoUn 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 proyectoEl contenido de los ficheros es el siguiente:
colores.txt
negromarrón
rojonaranjaamarilloverde
numeros.txt
cerounodostres
cuatrocinco
Crear un proyectoCreamos el proyecto a partir del contenido del directorio:
$ cvs import -m "Inicial" cursocvs cursocvs initialN cursocvs/numeros.txtN cursocvs/colores.txt
No conflicts created by this import
Proyecto creado, eliminamos el directorio temporal.
$ cd$ rm -rf /home/usuario/tmp
Trabajar en un proyectoCreamos 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.
$ lscursocvs
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 modificacionesCVS 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:
azulpúrpura
grisblanco
Comprobar modificacionesAccedemos al directorio del proyecto:
$ cd /home/usuario/work/cursocvs
Comprobar modificacionesComprobamos el estado de todos los ficheros:
$ cvs statuscvs 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 modificacionesComprobamos 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 modificacionesComprobamos los cambios de todos los ficheros:
$ cvs diffcvs 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 modificacionesComprobamos 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 modificacionesVemos los cambios de un solo fichero en dos columnas.
$ cvs diff --side-by-side colores.txtIndex: 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 parchesCuando 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 parchesUn 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 parchesUn ejemplo de generación de diffs sería el siguiente:
$ cvs diff colores.txt
Envíar modificacionesEnviamos 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.txtnew revision: 1.2; previous revision: 1.1
Envíar modificacionesAú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.txtnew revision: 1.3; previous revision: 1.2
Historial de los ficherosVemos el historial de versiones de todos los ficheros:
$ cvs logcvs 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 ficherosVemos el historial de versiones de un solo fichero:
$ cvs log colores.txtRCS 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 historialVer 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 historialVer 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 cambiosEs 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 cambiosPara 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 directoriosDurante 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 directoriosEl contenido del fichero dias.txt es el siguiente:
lunesmartes
miércolesjuevesviernessábado
domingo
Añadir nuevos ficheros y directoriosY ahora añadimos los ficheros al control de versiones:
$ cvs add fechas? fechas/dias.txtDirectory /var/lib/cvsd/tresnaola/cursocvs/fechas added to the repository
$ cvs add fechas/dias.txt cvs add: scheduling file `fechas/dias.txt' for additioncvs add: use `cvs commit' to add this file permanently
Añadir nuevos ficheros y directoriosFinalmente 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 ficherosPara renombrar un fichero se realiza el siguiente procedimiento:
1. Renombrar el fichero en local2. Eliminarlo del servidor3. Añadir el fichero local renombrado al control de versiones4. Subir el nuevo fichero al servidor
Renombrar ficherosEjemplo:
$ 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 directoriosPara renombrar un directorio se realiza el siguiente procedimiento:
1. Crear el nuevo directorio2. Añadirlo al control de versiones3. Mover los ficheros de un directorio al otro4. Eliminar el directorio anterior del control de versiones5. Añadir el nuevo directorio al control de versiones6. Aplicar los cambios en el servidor
Renombrar directoriosEjemplo:
$ 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 binariosCVS 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 binariosEs 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 binariosDe 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 binariosAl 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 temporal2. Quitarlo del control de versiones3. Renombrar el fichero temporal al nombre original4. Añadirlo al control de versiones con la opción kb5. Envíarlo al servidor CVS
Marcar ficheros como binarios (Escen. 1)Ejemplo:
$ cvs add documento.odtcvs add: scheduling file `documento.odt' for additioncvs add: use `cvs commit' to add this file permanently$ mv documento.odt tmp.odt$ cvs remove documento.odtcvs remove: removed `documento.odt'$ mv tmp.odt documento.odt$ cvs add -kb documento.odtcvs add: scheduling file `documento.odt' for additioncvs 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 servidor2. Resetear los flags del fichero local3. 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.odtRCS file: /var/lib/cvsd/tresnaola/cursocvs/documento.odt,vdone
$ cvs update -A documento.odtU doc.odt
$ cp /home/usuario/docs/documento.odt .$ cvs commit -m "Marcado como binario -kb"cvs commit: Examining .cvs commit: Examining fechas
cvswrappersPermiten 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.
cvswrappersSe 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
cvswrappersSe 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
cvsignoreDe 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.
cvsignoreLos 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.
cvsignorePor 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"
cvsignoreDe 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 equipoCuando 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 equipoPara 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 cursocvscvs checkout: Updating cursoCVSU cursoCVS/colores.txtU cursoCVS/numeros.txt
Trabajo en equipoAhora 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 equipoVolvemos 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 repositorioVemos el mensaje Status: Needs Patch.
Significa que la copia local necesita ser actualizada:
$ cvs updatecvs update: Updating .P numeros.txt
Resolución de conflictosHemos 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
CEROunodostrescuatro...
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
...cuatrocincoseisSIETE
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.txtnew 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 updatecvs update: Updating .RCS file: /var/lib/cvsd/tresnaola/cursocvs/numeros.txt,vretrieving revision 1.2retrieving revision 1.3Merging differences between 1.2 and 1.3 into numeros.txtM 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.txtCEROunodos...seisSIETE
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.txtnew 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 updatecvs 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.txtCEROichidos...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.txtnew 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.txtCERObatdos...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 updatecvs update: Updating .RCS file: /var/lib/cvsd/tresnaola/cursocvs/numeros.txt,vretrieving revision 1.4retrieving revision 1.5Merging differences between 1.4 and 1.5 into numeros.txtrcsmerge: warning: conflicts during mergecvs update: conflicts found in numeros.txtC 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.txtbat
=======ichi>>>>>>> 1.5dostrescuatro
cincoseisSIETE
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.txtCEROichibi...
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.txtnew revision: 1.6; previous revision: 1.5
Y actualizamos la copia local del otro desarrollador:
$ cd /home/usuario/work/cursocvs
$ cvs updatecvs update: Updating .P numeros.txt
TagsUn 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.
BranchEs 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 TagsSiempre 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 branchPara 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 branchPara 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 tagsPara 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 principalCuando 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íaPragmatic Version ControlUsing CVS
http://oreilly.com/catalog/9780974514000
Bibliografíazylk.net Wiki:
http://www.zylk.net/web/guest/web20/wiki//wiki/Main/CvsPrimerosPasos
¡Muchas gracias por su atención!
Joseba [email protected]
Top Related