Introducción al CVS : Tomando el Control

Versión 0.1 - Marzo 26 de 2003

Copyright (c) 2003 Nelson Castillo.

arhuaco (en) yahoo.com

La última versión de este documento se mantendrá en http://www.geocities.com/arhuaco/doc/introcvs/

Introducción

CVS es una herramienta realmente útil, aunque algo complicada. La motivación para escribir este documento es compartir los beneficios que estoy obteniendo al usar CVS con algunos de mis conocidos, y espero que con mis desconocidos también. No me considero experto en nada, así que las correcciones y contribuciones serán especialmente bienvenidas.

La idea es que usted pueda comenzar a utilizar CVS lo más rápido posible, esperando que con esto pueda ahorrar algún tiempo para leer los manuales de verdad. Si tiene un computador con GNU/Linux o una implementación similar de UNIX, es muy probable que ya tenga CVS instalado. En caso contrario, es probable que el contenido de este documento no sea de su interés. Existen tutoriales que indican como utilizar CVS en otros sistemas operativos. También existen herramientas gráficas que facilitan el uso de CVS. Acá haremos todo en la consola.

Supondré que está usando GNU/Linux y Bash. Si no, probablemente tendrá que cambiar una que otra cosa, sobre todo cuando se trata de manejar variables del entorno.

Esta es una versión preliminar e incompleta. Con su ayuda, podrá ser mejor.

Renuncia de Responsabilidad

De ninguna manera garantizo que la información aquí escrita está libre de errores ni que será inofensiva para su sistema. Es posible que su procesador implote al ejecutar alguna de las instrucciones aquí descritas. De igual forma, es posible que pierda por completo todos los respaldos de ese proyecto en el que ha estado trabajando durante cuatro años y que ya está por terminar. Proceda bajo su propia responsabilidad.

Agradecimientos

Este espacio está reservado para las personas que nos ayuden a mejorar este documento. Por el momento, un agradecimiento a todas las personas que escriben software libre por hacer de este un mundo mejor.


¿CVS? ¿Con Qué se Come?

CVS es un sistema de control de versiones. Usarlo te permite llevar una historia de tus códigos fuentes, algo como una historia clínica. Existe una horda de programadores superdotados que hacen copias periódicas de los fuentes de sus programas, y que tienen la extraordinaria habilidad para recordar -detalladamente- cada cambio que hacen. Cuando se descubre un error (comportamiento inesperado) en uno de sus programas, inmediatamente recuerdan la línea exacta y el archivo del código fuente que fue cambiado y proceden a arreglar el error. De igual forma, utilizan una red telepática de banda ancha que sirve para intercomunicar a todos los desarrolladores y mantenerlos al tanto de las últimas versiones del código fuente de sus programas.

Este método tiene el inconveniente de desperdiciar espacio en disco. CVS guarda solamente los cambios entre las diferentes versiones de cada archivo. Además, la gran mayoría de los mortales no tenemos esa extraordinaria capacidad en nuestra RAM ni sabemos telepatía, y por eso es mejor usar CVS. Usar CVS no solo ayuda a quien programa, sino a todos aquellos que puedan estar interesados en seguir el progreso de un proyecto de programación, de un conjunto de páginas de Internet, o de un libro. En general, de un conjunto de archivos.

CVS permite que varios desarrolladores trabajen concurrentemente en el desarrollo de un mismo programa. De esa forma, se facilita el desarrollo de programas por parte de un equipo. Esto no es transparente, y de vez en cuando se presentarán problemas -conflictos- cuando dos desarrolladores realicen cambios en el mismo archivo. Afortunadamente, CVS le informará a un usuario si el archivo que desea actualizar ya ha sido modificado para que pueda arreglar los cambios que se han hecho.

Además de tener un registro detallado de los cambios que se hacen a cada archivo del proyecto, CVS guarda etiquetas que se pueden asociar a una liberación. Así que en un momento determinado podemos decir, ``CVS, por favor marca este código fuente con la versión 0-0-9''. Esto permite que en el futuro, se pueda decir algo como ``Hey CVS, páseme la versión 0-0-9 del proyecto'', o algo como ``Hey CVS, ¿qué cosas han cambiado entre la versión 0-0-9 de mi proyecto y el código fuente que tengo ahora?''.

CVS es software libre distribuido bajo la Licencia GNU, lo cual indica que en lugar de imponer restricciones sobre el uso que los usuarios le pueden dar a la herramienta, la licencia de CVS preserva las libertades de los usuarios y de la comunidad.


¿Y Dónde Guarda CVS mis Fuentes?

Tranquilo, no las guarda en /dev/null. Para eso existe un repositorio, que es una localización central en la que se guarda el código fuente de varios proyectos. El repositorio puede ser local (en tu disco duro), o remoto. Acá trabajaremos con repositorios locales y remotos, de la forma más simple posible. Por esto, utilizaremos el protocolo SSH para acceder a los archivos remotos.

Creando un Repositorio Local

Así que manos a la obra, creemos un repositorio en tu cuenta de usuario. Para el nombre de la raíz del repositorio, he escogido 'cvs', pero puedes escoger otro nombre. Además, recuerda que voy a escribir en el directorio $HOME/cvs, así que ten cuidado. Para indicarle a CVS la ubicación de tu repositorio, puedes utilizar la opción -d en cada llamada, o crear una variable en el entorno llamada $CVSROOT. Esta variable se puede crear en el entorno de tu usuario con:

    $ export CVSROOT=$HOME/cvs

Suponiendo que usas Bash. Para verificar:

    $ echo $CVSROOT
  /home/n/cvs

Mi usuario es 'n', por supuesto en tu máquina aparecerá otra cosa dependiendo de tu login.

Puedes incluir esta línea -el export- en tu archivo $HOME/.bash_profile o $HOME/.bashrc para que siempre que inicies una sesión, la variable esté disponible en el entorno. Si no te gusta la idea, entonces no olvides pasar la opción -d$HOME/cvs en cada invocación al comando cvs.

Ahora procedemos a inicializar el repositorio:

    $ cvs init

si eres algo terco:

    $ cvs -d$HOME/cvs init

Bueno, ahora te recomiendo revisar los archivos y directorios que se crean en tu repositorio.

    $ ls -R $HOME/cvs
  /home/n/cvs:
  CVSROOT
  /home/n/cvs/CVSROOT:
  checkoutlist    config,v       Emptydir   modules,v  taginfo
  checkoutlist,v  cvswrappers    history    notify     taginfo,v
  commitinfo      cvswrappers,v  loginfo    notify,v   val-tags
  commitinfo,v    editinfo       loginfo,v  rcsinfo    verifymsg
  config          editinfo,v     modules    rcsinfo,v  verifymsg,v
  /home/n/cvs/CVSROOT/Emptydir:

Felicitaciones. Ya tienes un repositorio de CVS en tu disco duro local. Ahora, creemos un proyecto con el único propósito de ocupar espacio en nuestro recién creado repositorio. Usualmente, uno no maneja directamente los archivos que se encuentran dentro del repositorio sino que se invoca el programa cvs con diferentes opciones que permiten manipularlos.


Creando un Proyecto

Comenzaremos con un programa en C que cambiará el curso de la historia. Un programa en C que imprimirá la cadena ``Hola CVS''. El primer paso será crear un directorio en el que escribiremos el código fuente inicial.

    $ mkdir hola
    $ cd hola

Ahora, utilizando tu editor favorito, puedes crear el código fuente. Primero, un archivo llamado hola.c:

 -----------------------------
 #include <stdio.h>
 #include <stdlib.h>
 int
 main (int argc, char *argv[])
 {
   printf("Hola CVS");
   return EXIT_SUCCESS;
 }
 -----------------------------

Luego el archivo Makefile, que tendrá las instrucciones para compilar nuestro programa. Es importante notar que los espacios que aparecen antes de gcc no son espacios, es un TAB.

 -----------------------------
 # Makefile de ejemplo
 hola: hola.c
         gcc hola.c -o hola
 -----------------------------

Este será el primer proyecto que ingresará a nuestro repositorio. Toda una obra de arte. Recuerda que los archivos Makefile y hola.c deben estar en el directorio recién creado.

    $ ls
  hola.c  Makefile

Ahora vienen las palabras mágicas, la invocación al programa cvs.

    $ cvs import -m "Importando los fuentes" hola nelson inicio
  N hola/Makefile
  N hola/hola.c
  No conflicts created by this import

¡Funcionó! Se han importado los fuentes. Recuerda que debes tener la variable de entorno $CVSROOT asignada o utilizar la opción -d.

Ahora expliquemos los detalles, primero la acción import indica que lo que queremos hacer es 'importar' un proyecto al repositorio. Usualmente esto se hace cuando se quiere crear el proyecto a partir de archivos existentes, que es nuestro caso. Luego la cadena que se escribió con la opción -m, permite especificar una descripción a nuestra acción. La idea es que esté presente en cada modificación que hagamos al repositorio, para que cuando alguien muestre el historial de un archivo, le sea más fácil averiguar cual fue la razón del cambio. Un ejemplo de valores posibles para ésta cadena son:

  -m "arreglado el error que formateaba el disco duro"
  -m "cambié la llamada a gets por fgets"
  -m "ahora se imprime -Hola Mundo- en lugar de -Hola CVS-"

Esta cadena se utiliza con las demás acciones, no solo con import, y si no se especifica en la invocación, entonces se llamará a un editor para que se escriba esta descripción. El editor puede ser vim, emacs, nano o tu editor favorito. Puedes especificar tu editor preferido usando la variable del entorno $EDITOR. No deberías usar un editor gráfico, ya que no funcionaría en consola.

Bueno, no discutamos ahora si vim es mejor que emacs o lo contrario, mejor sigamos con las opciones de CVS. La palabra 'hola' indica el nombre del proyecto a crear. Este además será el nombre del directorio que contendrá el proyecto.

Luego tenemos la cadena 'nelson', que es una etiqueta que identifica al autor del proyecto (etiqueta del vendedor). No, no tiene que ser siempre nelson. Puedes cambiarla por tu nombre o el de tu empresa : esta la coloqué para hacerme publicidad.

Y finalmente, está la palabra 'inicio'. Esta es una marca que se pone a todos los fuentes del proyecto (etiqueta de la liberación). Recuerda que uno puede marcar el proyecto con diferentes etiquetas a través del tiempo para luego darle órdenes al CVS. Poner una nueva etiqueta no borra las anteriores.

Si eres lo suficientemente curioso, puedes ir a mirar tu repositorio local a ver que ha cambiado.

Ahora vamos a hacer modificaciones, con la protección de CVS. Voy a borrar el código fuente inicial, porque ya no lo necesitamos. En un proyecto de verdad sería buena idea guardar una copia de respaldo. Si, así como se hacía antes de CVS. ¿Tan rápido se te ha olvidado?

    $ rm Makefile hola.c
    $ cd ..
    $ rmdir hola

Bueno, no te preocupes. Ya sabes que las fuentes de nuestro gran programa están en el repositorio local.


Trabajando en el Proyecto

Ahora comenzamos a disfrutar de las ventajas de CVS. Vamos a crear una copia de trabajo, que será un directorio en el que estará una copia del proyecto que está en el repositorio. La idea es que cada desarrollador tenga su copia local y que vaya enviando los cambios al repositorio. No te desesperes. Un paso a la vez.

Para hacer cambios a los archivos que se encuentran en el repositorio de CVS se requiere tener permiso de escritura en el servidor. En la mayoría de los ejemplos de este documento trabajaremos con copias locales, así que esto no debe ser un problema.

Obteniendo una Copia del Proyecto

    $ cvs checkout hola
  cvs checkout: Updating hola
  U hola/Makefile
  U hola/hola.c

La acción checkout significa que se desea crear una copia local del proyecto 'hola'. Se crea entonces un directorio con el nombre del proyecto y dentro de él se crearan copias de los archivos y sub-directorios que hagan parte del mismo.

Ahora puedes entrar a la copia local de trabajo y ver que archivos tenemos.

    $ cd hola
    $ ls
  CVS  hola.c  Makefile

Y otra vez tenemos acceso a nuestros archivos, hola.c y Makefile. Aparece un directorio CVS que es utilizado por el programa cvs, no hace parte del proyecto. Entonces, veamos que hace nuestro programa. Primero lo compilamos.

    $ make
  gcc hola.c -o hola

Y luego lo corremos.

    $ ./hola
  Hola CVS[n@localhost hola]$

Cambiando Archivos del Proyecto

¡Hey! ¡Mira lo que pasó! ¡El programa tiene errores! Le falta un caracter '\n' al final de la cadena que imprimimos. Bueno, ya podemos hacer una modificación crucial a nuestro programa. Editamos el archivo y hacemos el cambio. Ya lo edité. No te voy a decir como. ¿Que cómo vas a saber que cambié? No hay problema, para eso está la acción diff, que permite ver que cambios se han hecho en los fuentes.

    $ cvs diff
  cvs diff: Diffing .
  Index: hola.c
  ===================================
  RCS file: /home/n/cvs/hola/hola.c,v
  retrieving revision 1.1.1.1
  diff -r1.1.1.1 hola.c
  7c7
  <   printf("Hola CVS");
  ---
  >   printf("Hola CVS\n");

Como puedes ver, he cambiado la línea

  printf("Hola CVS");

por

  printf("Hola CVS\n");

¡Impresionante!

Bueno, ya te habrás dado cuenta de que no todas las acciones llevan la opción -m, solo las que hacen cambios al repositorio.

Existe una mejor forma de realizar la opción diff, y es utilizando la opción -u.

    $ cvs diff -u
  cvs diff: Diffing .
  Index: hola.c
  ===================================
  RCS file: /home/n/cvs/hola/hola.c,v
  retrieving revision 1.1.1.1
  diff -u -r1.1.1.1 hola.c
  --- hola.c      26 Mar 2003 03:25:20 -0000      1.1.1.1
  +++ hola.c      26 Mar 2003 03:54:36 -0000
  @@ -4,7 +4,7 @@
   int
   main (int argc, char *argv[])
   {
  -  printf("Hola CVS");
  +  printf("Hola CVS\n");
     return EXIT_SUCCESS;
   }

Así se se imprime un poco más de texto y esto permite ver con mayor facilidad lo que se ha cambiado. Se utiliza un '+' para el código que se añade y un '-' para el código que se quita. La salida de cvs diff o de cvs diff -u es comprendida por el comando patch. Esto significa que es posible enviarle el texto aquí generado a alguien que tenga la versión anterior del proyecto 'hola', y el podrá utilizar el comando patch para convertir su código al nuevo. Por supuesto, con este código tan pequeño eso no tiene mucho sentido, pero los programas reales pueden ser más grandes, ¿cierto?. En todo caso, hablaremos de esto más tarde.

Es bueno que sepas que si alguna vez le envías un parche a alguien, deberías utilizar la opción -u! : se considera mala educación el no hacerlo. También existe el comando GNU diff por separado, como parte del paquete diffutils. Pero no te me distraigas, que estamos trabajando en el proyecto 'hola'.

Grabando los Cambios

Bueno, hemos mejorado en gran medida nuestro programa, pero los cambios que hemos hecho no están todavía en el repositorio. Así que si alguien hace un checkout en otro lado, tendrá la versión anterior de este programa. Guardemos los cambios.

    $ cvs commit -m "agregué un final de línea" hola.c
  Checking in hola.c;
  /home/n/cvs/hola/hola.c,v  <--  hola.c
  new revision: 1.2; previous revision: 1.1
  done

Ya hemos escrito los cambios al repositorio utilizando la acción commit. Como ves, la salida del programa nos dice que ahora la revisión del archivo hola.c es la 1.2 y que antes era la 1.1. En la invocación a cvs especifiqué que se iban a guardar los cambios del archivo hola.c. Si se omite el listado de archivos que se quieren cambiar entonces se hará un commit de todos los archivos que se hayan cambiado! Esto es particularmente molesto, así que debes tener cuidado. Si te equivocas es posible que guardes cambios que no querías guardar o que el comentario que habías pensado para un solo archivo se guarde para todos los archivos que se hayan modificado. ¿Recuerdas la opción -m?

Si ahora hago un cvs diff, no habrán cambios para mostrar.

    $ cvs diff -u
  cvs diff: Diffing .

Ahora, voy a hacer cambios... he he he...

    $ cvs diff -u
  cvs diff: Diffing .
  Index: Makefile
  ===================================
  RCS file: /home/n/cvs/hola/Makefile,v
  retrieving revision 1.1.1.1
  diff -u -r1.1.1.1 Makefile
  --- Makefile    26 Mar 2003 03:25:20 -0000      1.1.1.1
  +++ Makefile    26 Mar 2003 04:44:43 -0000
  @@ -2,3 +2,8 @@

   hola: hola.c
          gcc hola.c -o hola
  +
  +.PHONY: clean
  +
  +clean:
  +       rm hola
  Index: hola.c
  ===================================
  RCS file: /home/n/cvs/hola/hola.c,v
  retrieving revision 1.2
  diff -u -r1.2 hola.c
  --- hola.c      26 Mar 2003 04:29:49 -0000      1.2
  +++ hola.c      26 Mar 2003 04:43:29 -0000
  @@ -4,7 +4,10 @@
   int
   main (int argc, char *argv[])
   {
  -  printf("Hola CVS\n");
  +  printf("Este cambio no es deseado \n");

  +  if(argc>1)
  +    printf("%s\n", argv[1]);
  +
     return EXIT_SUCCESS;
   }

Desechando Cambios No Deseados

Bueno, he hecho cambios en los archivos Makefile y hola.c. Deseo guardar los cambios hechos en el primer archivo, pero no los que hice en el segundo. Ahora, ¿Quién podrá ayudarme? : update! Si hago cambios en un archivo y deseo volver a la copia que está en el repositorio, simplemente lo borro y hago un cvs update.

    $ rm hola.c
    $ cvs update hola.c
  cvs update: warning: hola.c was lost
  U hola.c

Ahora hacemos un diff

    $ cvs diff
  cvs diff: Diffing .
  Index: Makefile
  ===================================
  RCS file: /home/n/cvs/hola/Makefile,v
  retrieving revision 1.1.1.1
  diff -r1.1.1.1 Makefile
  4a5,9
  >
  > .PHONY: clean
  >
  > clean:
  >       rm hola

Ahora solamente quedan los cambios que hice en el archivo Makefile y puedo proceder a guardarlos.

    $ cvs commit -m "adicioné el target clean" Makefile
  Checking in Makefile;
  /home/n/cvs/hola/Makefile,v  <--  Makefile
  new revision: 1.2; previous revision: 1.1
  done

Solamente guardé los cambios que me interesaban. Nuestra copia local está sincronizada con el repositorio. Ahora podemos borrar los fuentes locales y hacer un cvs checkout la próxima vez que vayamos a trabajar con el repositorio.

  $ cvs diff
  cvs diff: Diffing .

Es conveniente notar que el texto ``cvs diff: Diffing .'' se escribe a stderr, mientras que las diferencias se imprimen a stdout. Esto nos permite enviar la salida del cvs diff a un archivo para luego revisarlo con un editor que tenga realce de sintaxis o para enviarle los cambios a alguien por email.

    $make clean
    $ cvs diff -u > /tmp/hola.patch
  cvs diff: Diffing .
    $ vim /tmp/hola.patch
    $ cat /tmp/hola.patch | mail -s "Los cambios que hice" [email protected]
    $ echo =\)

Adicionando Archivos al Proyecto

Vamos a añadir un archivo al proyecto, se llamará LEAME. Crearé el archivo con el comando cat. Si, puedes crearlo con un editor si quieres.

    $ cat > LEAME << "EOF"
    > hola
    >
    > Este es un proyecto que cambiará el mundo.
    >
    > Chao.
    > EOF

Y listo. Ahora miremos que hay en el directorio del proyecto.

    $ ls
  CVS  hola.c  LEAME  Makefile

Apareció el LEAME. Hagamos un diff.

    $ cvs diff * > /tmp/hola.patch
  cvs diff: I know nothing about LEAME
  cvs diff: warning: directory CVS specified in argument
  cvs diff: but CVS uses CVS for its own purposes; skipping CVS directory

Recuerda que estamos viendo lo que se imprime al error estándar (stderr). Mira que he utilizado un asterisco (*) y el programa cvs me ha regañado, traduciré : ``Loco, no sé nada del documento LEAME. Ese archivo no hace parte del proyecto''. Personalmente, suelo invocar al cvs de ésta manera con frecuencia, para ver si se me ha olvidado poner algo en el proyecto. Si acá aparecen archivos intermedios generados por LaTeX, gcc, o por cualquier otro programa de aplicación, entonces puedes ignorar los mensajes de error que estos producirán. Debes tener especial cuidado y añadir los que si hacen parte del proyecto, para que no se pierdan.

Entonces, agreguemos el archivo LEAME.

    $ cvs add LEAME
  cvs add: scheduling file `LEAME' for addition
  cvs add: use 'cvs commit' to add this file permanently

El archivo se ha programado para adición. Hagamos el commit.

    $ cvs commit -m "Las instrucciones" LEAME
  RCS file: /home/n/cvs/hola/LEAME,v
  done
  Checking in LEAME;
  /home/n/cvs/hola/LEAME,v  <--  LEAME
  initial revision: 1.1
  done

Se ha añadido el archivo.

Adicionando Directorios al Proyecto

Vamos a adicionar un directorio llamado doc con instrucciones de instalación.

    $ mkdir doc
    $ cvs add doc
  Directory /home/n/cvs/hola/doc added to the repository

No es necesario hacer un commit, pero para que el directorio tenga sentido, deberíamos crear un archivo dentro de él.

    $ cat > doc/INSTALAR << "EOF"
    > No debe hacer nada para instalar.
    > EOF

    $ ls doc/
  INSTALAR

Bueno, ahora vamos a adicionar el archivo INSTALAR

    $ cvs add doc/INSTALAR
  cvs add: scheduling file `doc/INSTALAR' for addition
  cvs add: use 'cvs commit' to add this file permanently
    $ cvs commit -m "instrucciones de instalación" doc/INSTALAR
  RCS file: /home/n/cvs/hola/doc/INSTALAR,v
  done
  Checking in doc/INSTALAR;
  /home/n/cvs/hola/doc/INSTALAR,v  <--  INSTALAR
  initial revision: 1.1
  done

Y listo. Ya tenemos un directorio nuevo que contiene un archivo. Si hacemos un diff, ya se revisa el contenido del directorio.

ADVERTENCIA:Recuerda que no se revisarán los archivos que no estén en el repositorio.

    $ cvs diff 
  cvs diff: Diffing .
  cvs diff: Diffing doc

Voy a modificar el archivo recién creado:

  $ echo "Y cvs no es del todo fácil" >> doc/INSTALAR

Y ahora miremos que ha cambiado:

    $ cvs diff -u
  cvs diff: Diffing .
  cvs diff: Diffing doc
  Index: doc/INSTALAR
  ===================================
  RCS file: /home/n/cvs/hola/doc/INSTALAR,v
  retrieving revision 1.1
  diff -u -r1.1 INSTALAR
  --- doc/INSTALAR        26 Mar 2003 06:38:28 -0000      1.1
  +++ doc/INSTALAR        26 Mar 2003 06:42:53 -0000
  @@ -1 +1,2 @@
   No debe hacer nada para instalar.
  +Y cvs no es del todo fácil

Borrando Archivos del Proyecto

Sabes que ese archivo LEAME ya no me gusta. Vamos a borrarlo.

    $ rm LEAME
    $ ls
  CVS  doc  hola.c  Makefile

Ahora utilizamos cvs remove para borrar el archivo.

    $ cvs remove LEAME
  cvs remove: scheduling `LEAME' for removal
  cvs remove: use 'cvs commit' to remove this file permanently

Para que quede completamente borrado, se bebe usar cvs commit.

    $ cvs commit -m "Chao LEAME" LEAME
  Removing LEAME;
  /home/n/cvs/hola/LEAME,v  <--  LEAME
  new revision: delete; previous revision: 1.1.1.1
  done

Y ya hemos borrado el archivo.

Borrando Contenido de Directorios del Proyecto

Bueno, ese directorio doc nos ha dado como que muchos problemas. Vamos a borrarlo.

    $ cvs remove doc
  cvs remove: Removing doc
  cvs remove: scheduling `doc/INSTALAR' for removal
  cvs remove: use 'cvs commit' to remove this file permanently
    $ cvs commit -m "borrando dentro de doc" doc
  Removing doc/INSTALAR;
  /home/n/cvs/hola/doc/INSTALAR,v  <--  INSTALAR
  new revision: delete; previous revision: 1.1
  done

Ahora viene el borrado del directorio. Para esto simplemente hay que... hey... espera... en CVS no se borran los directorios. Para que los directorios que están vacíos no se vean la próxima vez que hagas un checkout, puedes agregar la opción -P. Esta opción hace que los directorios vacíos no aparezcan.

¿Y qué Hago con mi Copia Local Cuando Termino?

Buena pregunta. Puedes simplemente borrarla, pero lo mejor es indicarle primero al CVS que quieres abandonar tu copia local.

    $ cd ..
    $ cvs release hola
  You have [0] altered files in this repository.
  Are you sure you want to release directory `hola': y

Al hacer un cvs release, CVS te advertirá si estas borrando un archivo con cambios a los que no has hecho commit, y también te advertirá si hay un archivo nuevo que no ha sido añadido al repositorio. Si además quieres borrar tu copia local, entonces puedes usar la opción -d.

    $ cd ..
    $ cvs release -d hola
  You have [0] altered files in this repository.
  Are you sure you want to release (and delete) directory `hola': y


Sincronizando la Copia Local con el Repositorio

Si varios desarrolladores están trabajando con un mismo repositorio es posible que alguien haya hecho un cambio a uno de los archivos que están en tu copia local. Haremos una prueba para mostrar lo que puede pasar.

Primero, hacemos un checkout del proyecto en $HOME/prueba.

    $ mkdir prueba && cd prueba
    $ cvs checkout -P hola
  cvs checkout: Updating hola
  U hola/Makefile
  U hola/hola.c
  cvs checkout: Updating hola/doc

Ahora dupliquemos nuestra copia local en otro directorio. Si, también pudimos haber hecho un checkout en otro lado.

    $ cp hola hola1 -R
    $ ls
  hola  hola1

Entremos a hola1, hagamos un cambio y hacemos un commit.

    $ cd hola1

Hago el cambio con mi editor favorito...

    $ cvs diff -u
  cvs diff: Diffing .
  Index: hola.c
  ===================================
  RCS file: /home/n/cvs/hola/hola.c,v
  retrieving revision 1.1.1.1
  diff -u -r1.1.1.1 hola.c
  --- hola.c      26 Mar 2003 06:17:36 -0000      1.1.1.1
  +++ hola.c      26 Mar 2003 09:08:22 -0000
  @@ -5,6 +5,7 @@
   main (int argc, char *argv[])
   {
     printf("Hola CVS\n");
  +  printf("Hola de nuevo");

     return EXIT_SUCCESS;
   }

y luego hago un commit.

    $ cvs commit -m "Ahora digo hola dos veces" hola.c
  Checking in hola.c;
  /home/n/cvs/hola/hola.c,v  <--  hola.c
  new revision: 1.2; previous revision: 1.1
  done

Viendo el Estado del Repositorio

Hemos actualizado el repositorio, pero hay una copia que tiene la versión anterior. Entonces podemos entrar al otro directorio y suponer que los cambios que acabamos de hacer fueron hechos por otra persona.

    $ cd ..
    $ cd hola
    $ cvs status
  cvs status: Examining .
  ===================================
  File: Makefile          Status: Up-to-date
     Working revision:    1.1.1.1 Wed Mar 26 06:17:36 2003
     Repository revision: 1.1.1.1 /home/n/cvs/hola/Makefile,v
     Sticky Tag:          (none)
     Sticky Date:         (none)
     Sticky Options:      (none)
  ===================================
  File: hola.c            Status: Needs Patch
     Working revision:    1.1.1.1 Wed Mar 26 06:17:36 2003
     Repository revision: 1.2     /home/n/cvs/hola/hola.c,v
     Sticky Tag:          (none)
     Sticky Date:         (none)
     Sticky Options:      (none)

Como puedes ver, el archivo hola.c necesita un parche ('Needs Patch'). Entonces podríamos hacer una actualización del repositorio local, y se vería algo como esto:

    $ # cvs update # no lo vamos a ejecutar... por eso el '#' al inicio
  cvs update: Updating.
  U hola.c

Pero como eso sería muy fácil, vamos a hacer las cosas más interesantes y vamos a hacerle una modificación inocua al Makefile y un cambio local al archivo hola.c, que ya ha cambiado en el repositorio.

Cambiando... Listo. Veamos lo que hice:

    $ cvs diff -u
  cvs diff: Diffing .
  Index: Makefile
  ===================================
  RCS file: /home/n/cvs/hola/Makefile,v
  retrieving revision 1.3
  diff -u -r1.3 Makefile
  --- Makefile    26 Mar 2003 09:57:59 -0000      1.3
  +++ Makefile    26 Mar 2003 09:58:17 -0000
  @@ -1,4 +1,5 @@
   # Makefile de ejemplo
  +# un comentario tonto

   hola: hola.c
          gcc hola.c -o hola
  Index: hola.c
  ===================================
  RCS file: /home/n/cvs/hola/hola.c,v
  retrieving revision 1.1.1.1
  diff -u -r1.1.1.1 hola.c
  --- hola.c      26 Mar 2003 06:17:36 -0000      1.1.1.1
  +++ hola.c      26 Mar 2003 09:22:24 -0000
  @@ -5,6 +5,7 @@
   main (int argc, char *argv[])
   {
     printf("Hola CVS\n");
  +  printf("Imprimo otra cosa. Lero lero.");

     return EXIT_SUCCESS;
   }

Así que ahora se puede ver como están las cosas:

    $ cvs status
  cvs status: Examining .
  ===================================
  File: Makefile          Status: Locally Modified
     Working revision:    1.1.1.1 Wed Mar 26 06:17:36 2003
     Repository revision: 1.1.1.1 /home/n/cvs/hola/Makefile,v
     Sticky Tag:          (none)
     Sticky Date:         (none)
     Sticky Options:      (none)
  ===================================
    File: hola.c            Status: Needs Merge
     Working revision:    1.1.1.1 Wed Mar 26 06:17:36 2003
     Repository revision: 1.2     /home/n/cvs/hola/hola.c,v
     Sticky Tag:          (none)
     Sticky Date:         (none)
     Sticky Options:      (none)

Puedes utilizar GNU grep para filtrar la salida de cvs status. Como me da pereza leer sobre la sintaxis de las expresiones regulares de grep, usaré el programa perl.

    $ cvs status | perl -nwe 'print if(/Merge|Modified|Patch|conflicts/)'
  cvs status: Examining .
  File: Makefile          Status: Locally Modified
  File: hola.c            Status: Needs Merge

Recuerda que la primera línea va a stderr, por eso no se filtró. Bueno, no comencemos con discusiones religiosas sobre SED y AWK versus Perl. Siempre lo mismo contigo. Que cosa.

Resumiendo, los estados que hemos visto para los archivos son:

Up-to-date
El archivo está igual que el del repositorio.

Locally Modified
Lo hemos modificado localmente. Podemos hacer commit. Una práctica prudente sería modificar archivos en el repositorio solamente después de haber arreglado los archivos que están en estado Needs Merge y de haber leído las diferencias (con diff -u), aplicado y probado los parches. Esto debido a que aunque los archivos son independientes, el programa o documento puede tener interdependencias y si hacemos commit se puede armar un desorden.

Needs Patch
Alguien lo cambió y podemos actualizarlo. Fácil.

Needs Merge
Alguien lo cambió y también lo hemos cambiado localmente. Como es el caso más complejo, lo analizaremos. Hay que mezclar los cambios hechos localmente con los cambios que hizo la otra persona.

File had conflicts on merge
Se hizo un merge y el archivo tuvo conflictos. Estos se resuelven a mano.

Resolviendo Conflictos al Hacer 'Merge'

Una forma más o menos fácil puede ser mover la copia local del archivo a otro lado, luego hacer un update para ver lo que cambió la otra persona, y luego hacer de nuevo las modificaciones que inicialmente queríamos hacer. Aunque esto suena complicado. Probemos mezclando lo que hizo la otra persona (Hipotética) con lo que hemos hecho, y resolvemos los conflictos a mano.

    $ cvs update hola.c
  RCS file: /home/n/cvs/hola/hola.c,v
  retrieving revision 1.1.1.1
  retrieving revision 1.2
  Merging differences between 1.1.1.1 and 1.2 into hola.c
  rcsmerge: warning: conflicts during merge
  cvs update: conflicts found in hola.c
  C hola.c

Hubo conflictos en el merge porque modificamos líneas comunes, por lo que debemos leer y arreglar a mano. Si todo suena muy complicado, siempre podemos volver a la versión anterior de un archivo. Puede ser recomendable hacer una copia de lo que queríamos hacer antes de llamar a cvs update. Si alguien hace ahora un checkout del proyecto mientras estamos resolviendo el conflicto, él no se va a enterar. Pero es bueno que hagamos el commit rápido para que los demás puedan hacer un update o un merge lo más pronto posible.

Si nosotros hacemos un cvs status, veremos entre las líneas de la salida una línea en particular que dice:

  File: hola.c            Status: File had conflicts on merge

Los demás no se darán cuenta. Usualmente, una lista de discusión es muy útil en combinación con el CVS, ya que así los programadores pueden avisar cuando tienen intenciones de hacer un cambio en un archivo que es mantenido por varias personas. CVS no define las políticas que el grupo de desarrollo implementa.

Observa como ve el archivo hola.c la persona que hizo el merge. Es decir, como lo vemos nosotros. No se te olvide, estamos metidos en este problema.

  -----------------------------
  #include <stdio.h>
  #include <stdlib.h>
  int
  main (int argc, char *argv[])
  {
    printf("Hola CVS\n");
  <<<<<<< hola.c
    printf("Imprimo otra cosa. Lero lero.");
  =======
    printf("Hola de nuevo");
  >>>>>>> 1.2

    return EXIT_SUCCESS;
  }
  -----------------------------

Bueno, es hora de arreglar las diferencias con el programador hipotético. Resolvamos el conflicto, separado por '======='. Como Las acciones no son exclusivas ni se estorban, podemos dejar el programa de la siguiente manera:

  -----------------------------
  #include <stdio.h>
  #include <stdlib.h>
  int
  main (int argc, char *argv[])
  {
    printf("Hola CVS\n");
    printf("Imprimo otra cosa. Lero lero.");
    printf("Hola de nuevo");
    return EXIT_SUCCESS;
  }
  -----------------------------

Y luego podemos hacer commit, y nadie tiene por qué enterarse del problema. De hecho, no hay problemas... ¿Quién ha visto uno?

    $ cvs commit -m "Imprimo lero lero" hola.c
  Checking in hola.c;
  /home/n/cvs/hola/hola.c,v  <--  hola.c
  new revision: 1.3; previous revision: 1.2
  done

Haciendo Merge sin Generar un Conflicto

Para complementar, veamos una prueba en la que no se presentan conflictos.

    $ cvs update hola.c
  RCS file: /home/n/cvs/hola/hola.c,v
  retrieving revision 1.2
  retrieving revision 1.3
  Merging differences between 1.2 and 1.3 into hola.c
  M hola.c

Ahora el estado del archivo es:

  File: hola.c            Status: Locally Modified
     Working revision:    1.3     Result of merge
     Repository revision: 1.3     /home/n/cvs/hola/hola.c,v
     Sticky Tag:          (none)
     Sticky Date:         (none)
     Sticky Options:      (none)

Y podemos ver el diff:

    $ cvs diff
  cvs diff: Diffing .
  Index: hola.c
  ===================================
  RCS file: /home/n/cvs/hola/hola.c,v
  retrieving revision 1.3
  diff -r1.3 hola.c
  3a4,5
  > /* TODO: hacer algo mejor */
  >
  9a12
  >   printf ("Hola otra vez");
  cvs diff: Diffing doc

Para aclarar, el comentario 'TODO: hacer algo mejor' fue agregado por el usuario hipotético. El cambio 'printf (``Hola otra vez'');' lo hice yo. Como vez, el diff es un poco difícil de entender. Solo quise mostrarte por qué hay que usar la opción -u. En todo caso, si nada se ha dañado podemos hacer commit.

    $ cvs commit -m "imprimo más cosas" hola.c
  Checking in hola.c;
  /home/n/cvs/hola/hola.c,v  <--  hola.c
  new revision: 1.4; previous revision: 1.3
  done

Todos felices y comemos perdices.


Distribuyendo copias del proyecto

Ha llegado la hora de mostrar nuestro trabajo al mundo. Para esto podemos exportar el contenido del repositorio. La diferencia entre cvs export y cvs checkout es que cvs export crea una copia del repositorio, lista para ser entregada al público, sin directorios auxiliares.


    $ mkdir prueba
    $ cd prueba
    $ cvs export -D "1 seconds ago" hola
  cvs export: Updating hola
  U hola/Makefile
  U hola/hola.c
  cvs export: Updating hola/doc
    $ls hola
  hola.c  Makefile

Como ven, el contenido del directorio 'hola' no incluye los directorios que están vacíos. Este último efecto se puede conseguir con un cvs checkout si se le pasa la opción -P. Como ejemplo hemos exportado el código que estaba en el repositorio hace un segundo. Se puede exportar el que estaba la semana pasada, hace un mes, etc. O se puede utilizar una etiqueta:

    $ cvs export -r 'inicio' hola

En este caso se usaría la etiqueta 'inicio'.

Ahora ya puedes:

    $ tar cvf hola.tar hola
  hola/
  hola/Makefile
  hola/hola.c
    $ gzip -9 hola.tar

Y si compila, ya lo podemos liberar =)


Liberando Parches

Cuando los proyectos crecen, van creciendo en tamaño y por lo tanto cada liberación ocupará más bytes. Larry Wall (el creador de Perl) escribió la versión original del programa patch. Como dije antes, el programa patch puede entender la salida de diff o de diff -u.

Ya te imaginarás para qué sirve todo esto. Si uno ya ha bajado un programa y para la siguiente versión del programa el autor publica los parches, entonces no es necesario bajar todo el programa, solo se bajan los parches. ¿Así que tu bajas la kernel de Linux siempre? Con razón se pone lento el servidor... Bueno, ya sabes que de ahora en adelante debes bajar los parches.

Si uno no espera que un parche sea leído detalladamente por humanos, está bien no usar -u para ahorrar espacio. De lo contrario, siempre se debería usar la opción -u.

Ya sabes como usar cvs export. Ahora hagamos un parche. Mira que usaremos la etiqueta 'inicio', que fue usada para crear el repositorio al comienzo de este documento.

Entonces, hagamos lo siguiente:

Obteniendo los fuentes de una liberación anterior con su etiqueta

¿Recuerdas que te conté que podías tener cualquier versión? No te estaba mintiendo. Vamos a obtener el código inicial.

    $ mkdir $HOME/test1
    $ cd $HOME/test1
    $ cvs checkout -P -r inicio hola
  cvs checkout: Updating hola
  U hola/LEAME
  U hola/Makefile
  U hola/hola.c
  cvs checkout: Updating hola/doc

¡Hey, que pasa! ¡ LEAME no estaba en la liberación inicial! Bueno, lo que pasó fue que en algún momento cometí un error y entonces decidí borrar el repositorio y crearlo de nuevo con unos fuentes que ya tenían el archivo LEAME. Así que en esta sección, esos son los fuentes iniciales. Si, estoy apenado contigo.

Veamos un tree del directorio hola:

    $ tree  hola
  hola
  1-- CVS
  1   1-- Entries
  1   1-- Repository
  1   1-- Root
  1   `-- Tag
  1-- LEAME
  1-- Makefile
  `-- hola.c

Consultando la Bitácora de un archivo

Podemos ver la historia de los cambios realizados a los archivos del código fuente:

    $ cd hola
    $ cvs log LEAME
  RCS file: /home/n/cvs/hola/Attic/LEAME,v
  Working file: LEAME
  head: 1.2
  branch:
  locks: strict
  access list:
  symbolic names:
          inicio: 1.1.1.1
          nelson: 1.1.1
  keyword substitution: kv
  total revisions: 3;     selected revisions: 3
  description:
  ----------------------------
  revision 1.2
  date: 2003/03/26 06:49:42;  author: n;  state: dead;  lines: +0 -0
  Chao LEAME
  ----------------------------
  revision 1.1
  date: 2003/03/26 06:17:36;  author: n;  state: Exp;
  branches:  1.1.1;
  Initial revision
  ----------------------------
  revision 1.1.1.1
  date: 2003/03/26 06:17:36;  author: n;  state: Exp;  lines: +0 -0
  nuevas fuentes viejas

Aquí se ve la historia del archivo LEAME, que al final fue borrado. El nombre del archivo es opcional, si no se especifica, se muestra la historia de los archivos del proyecto. No te me distraigas, estamos haciendo parches.

Ahora, vamos a generar un parche que actualice la versión inicial a la versión actual. Para eso voy a hacer lo siguiente:

    $ cvs ..
    $ mv hola hola_inicial
    $ cvs checkout -P hola
  cvs checkout: Updating hola
  U hola/Makefile
  U hola/hola.c
  cvs checkout: Updating hola/doc

Hemos obtenido la versión actual.

    $ tree hola
  hola
  1-- CVS
  1   1-- Entries
  1   1-- Repository
  1   `-- Root
  1-- Makefile
  `-- hola.c

Y no aparece el infame archivo LEAME. Vamos a hacer un parche para que los usuarios que tienen la liberación inicial de nuestro programa puedan actualizarse sin problemas. Bueno, imaginemos que ese es el caso.

    $ cd hola
    $ cvs rdiff -r 'inicio' hola > ../hola-inicio_final.patch
    cvs rdiff: Diffing hola
    cvs rdiff: Diffing hola/doc

Hemos generado el parche que convierte los fuentes de la distribución marcada 'inicio' con los de la distribución... que vamos a marcar como final.

Marcando el Código Fuente

    $ cvs tag -c final .
  cvs tag: Tagging .
  T Makefile
  T hola.c

La opción -c es útil debido a que la etiqueta se coloca al al código que está en el repositorio, y no al código local. Esta opción verifica que el código de la copia local esté al día con el del repositorio antes de colocar la etiqueta. ¡No te distraigas! Estamos haciendo un parche.

Aplicando el Parche

Seguimos con el parche... el parche que creamos está en el archivo ../hola-inicio_final.patch, vamos a leerlo.

  Index: hola/LEAME
  diff -c hola/LEAME:1.1.1.1 hola/LEAME:removed
  *** hola/LEAME:1.1.1.1  Wed Mar 26 01:17:36 2003
  --- hola/LEAME  Wed Mar 26 07:16:59 2003
  ***************
  *** 1,5 ****
  - hola
  -
  - Este es un proyecto que cambiará el mundo.
  -
  - Chao.
  --- 0 ----
  Index: hola/Makefile
  diff -c hola/Makefile:1.1.1.1 hola/Makefile:1.4
  *** hola/Makefile:1.1.1.1 Wed Mar 26 01:17:36 2003
  --- hola/Makefile Wed Mar 26 05:41:34 2003
  ***************
  *** 1,4 ****
  --- 1,5 ----
    # Makefile de ejemplo
  + # un comentario tonto

    hola: hola.c
      gcc hola.c -o hola
  Index: hola/hola.c
  diff -c hola/hola.c:1.1.1.1 hola/hola.c:1.4
  *** hola/hola.c:1.1.1.1 Wed Mar 26 01:17:36 2003
  --- hola/hola.c Wed Mar 26 05:50:19 2003
  ***************
  *** 1,10 ****
  --- 1,15 ----
    #include <stdio.h>
    #include <stdlib.h>

  + /* TODO: hacer algo mejor */
  +
    int
    main (int argc, char *argv[])
    {
      printf("Hola CVS\n");
  +   printf("Imprimo otra cosa. Lero lero.");
  +   printf("Hola de nuevo");
  +   printf("Hola otra vez");

      return EXIT_SUCCESS;
    }

Y ahora lo aplicamos al código que está en el directorio hola_inicial.

    $ cd ..
    $ cd hola_inicial
    $ cat ../hola-inicio_final.patch | patch
  patching file LEAME
  patching file Makefile
  patching file hola.c

Y listo. El parche se ha aplicado. Ten en cuenta que en el directorio hola_inicial hay un checkout, ¡no un export! El archivo LEAME ha quedado, pero ahora está vacío. Si miras la página del manual de patch notarás que existe una opción --remove-empty-files, que borra los archivos que quedan vacíos después de aplicar el parche. Puedes comprobar que las versiones ahora son iguales con un diff. Mira que es la primera vez que uso el programa diff, ¡que es diferente de cvs diff!

    $pwd
  /home/n/test1/hola_inicial
    $ diff hola.c ../hola/hola.c
    $ diff Makefile ../hola/Makefile
    $ cat LEAME

diff no muestra diferencias entre los archivos, porque no hay diferencias. Nuestro parche los ha hecho iguales.

Ahora queda de tu parte mirar el manual para ver como se pueden hallar las diferencias entre dos etiquetas. Esta bien, una pista:

    $ cvs rdiff -r 'inicio' -r 'final' hola

debería producir un parche igual al que usamos en este ejemplo.

    $ cvs rdiff -r 'final' -r 'inicio' hola

La última línea crea un parche (por lo menos hace el diff) que convierte la versión etiquetada 'final' a la etiquetada 'inicio'. No consumas bebidas con alcohol antes de crear o aplicar parches.


Accediendo el Repositorio Remoto con SSH

Un repositorio CVS puede estar en una máquina local, o en un servidor remoto mientras puedas conectarte a él con SSH (shell seguro). Existen otras formas de conectarse a un servidor CVS por red. Consideraremos la forma más simple por el momento.

Primero, debes decirle al programa cvs que deseas usar el programa ssh para establecer la conexión remota. Por estos días, casi nadie utiliza rsh en servidores conectados a Internet porque es inseguro, así que utilizaremos el programa ssh. Además, puedes especificar de una vez el $CVSROOT, para que no tengas que utilizar la opción -d en cada llamada a cvs.

    $ export CVS_RSH=ssh
    $ export CVSROOT=:ext:[email protected]:/home/n/cvs

Puedes añadir esto a tu $HOME/.bash_profile. En la siguiente invocación, debes reemplazar n por tu login en la servidor remoto, y 127.0.0.1 por la IP o el nombre del servidor en cuestión. He tomado estos valores como ejemplo, y haré una conexión por ssh a una dirección IP local.

    $ cvs checkout hola
  [email protected]'s password:
  cvs server: Updating hola
  U hola/Makefile
  U hola/hola.c
  cvs server: Updating hola/doc

Ahora, hagamos alguna operación:

    $ cd hola/
    $ cvs diff
  [email protected]'s password:
  cvs server: Diffing .
  cvs server: Diffing doc

Bueno, un pequeño inconveniente es que debes escribir la contraseña del servidor para cada operación que realices. Esto tiene solución, es posible generar una llave en el servidor remoto y tenerla también en la máquina local, para que puedas hacer login con ssh sin necesidad de escribir el password. Esto tiene sus riesgos, así que solamente te diré que es posible hacerlo. ¿Se debería añadir esto a la documentación?


Avanzado

En esta sección se escribirán brevemente cosas que están por fuera del alcance de este documento introductorio. Entre otras cosas, por que no soy todavía competente en ellas. Eso de 'Avanzado' siempre es relativo.

Inconvenientes de CVS

Una vez que has guardado los cambios de un grupo de archivos, CVS se olvida de este cambio como un todo. La bitácora que se lleva es sobre cada archivo del repositorio.

Guardado Selectivo

No es necesario guardar todos los archivos de un programa. Puede ser un desperdicio muy grande -por no nombrar las molestias- guardar archivos que sean generados automáticamente por el mismo programa, o por programas que deben estar en la plataforma de destino. Esto suele pasar cuando se está utilizando Autoconf. Se puede ejecutar un ``make distclean'' antes de importar los fuentes al repositorio, ya que muchas cosas se generan cuando invocas el 'configure'. Tu sabrás que hacer.

Configuración Personalizada

Como hemos visto en el documento, puedes utilizar el archivo $HOME/.bash_profile para guardar algunas preferencias. Mira la documentación de CVS si quieres saber más acerca de las variables del entorno que afectan su comportamiento.

También puedes crear un archivo $HOME/.cvsrc que guarde algunas preferencias acerca del uso del porgrama cvs.

Ejemplo del archivo $HOME/.cvsrc:

     diff -u
     update -P
     checkout -P

Esto hará que la opción que aparece al frente de cada acción se utilice siempre que se ejecute el programa cvs con la acción correspondiente. Así no olvidarás hacer los diffs con la opción -u, si ejecutas algo como:

    $ cvs diff | mail -s "cambios" [email protected]

Branching and Merging

Es posible bifurcar las versiones de las fuentes de un programa en diferentes ramas de desarrollo. De esa forma, los autores pueden trabajar sobre diferentes versiones del software. Esto no lo he usado. Puede servir para corregir algunos errores en una versión anterior de un programa para el que se quieren proveer actualizaciones. Por ejemplo, un parche que corrige problemas de seguridad. También se puede usar para que un programador haga un desarrollo experimental en una parte del código, que estará alojado en el mismo repositorio.

Archivos binarios

Bueno, hay veces que es útil importar archivos binarios al repositorio. Por ejemplo, imágenes de una página WEB. Acá haremos algo muy horrible con el único propósito de mostrar que si se puede.

    $ cvs checkout hola
    $ cd hola
    $ make
  gcc hola.c -o hola
    $ cvs add -kb hola
  cvs add: scheduling file `hola' for addition
  cvs add: use 'cvs commit' to add this file permanently
    $ cvs commit -m "que feo" hola
  RCS file: /home/n/cvs/hola/hola,v
  done
  Checking in hola;
  /home/n/cvs/hola/hola,v  <--  hola
  initial revision: 1.1
  done
    $ rm hola
    $ cvs update hola
  cvs update: warning: hola was lost
  U hola
    $ ./hola
  Hola CVS
  Imprimo otra cosa. Lero lero.Hola de nuevoHola otra vez

La clave : invocamos el cvs add con la opción -kb. ¿Como se verá un cvs diff de un binario? No, no salen cosas graciosas en la consola. Después de hacer cambios... :

    $ cvs diff hola
  Index: hola
  ============================
  RCS file: /home/n/cvs/hola/hola,v
  retrieving revision 1.1
  diff -r1.1 hola
  Binary files /tmp/cvswUeSBR and hola differ

Backups

Puedes hacer backups del repositorio. CVS no tiene forma de detectar si algunos archivos del repositorio se han dañado. Esto es grave, pero igual esto podría afectar tus fuentes normales. Averigua un poco más y actualiza ésta sección.


Conclusión

Al utilizar CVS se pierde el miedo de probar nuevas cosas, ya que casi siempre se puede volver atrás y es más fácil tener control sobre el proyecto que se está realizando. Hay que pagar un precio : aprender a utilizar la herramienta. Como es probable que de vez en cuando se cometan errores graves, las copias de respaldo son la primera línea de defensa.

Al principio, será un poco tedioso usar CVS, pero en unas horas te preguntarás cómo pudiste vivir tanto tiempo sin usarlo. CVS no es un sustituto de buenas prácticas de programación y mucho menos del correcto manejo de un proyecto. Es solamente una buena ayuda.

Ahora ve donde tu amigo o amiga, y pregunta irónicamente: ¿Ya sabes usar CVS?


Referencias

http://www.cvshome.org/ : La casa de CVS en Internet / Manual en línea.

man cvs : Página del Manual

info cvs : Documentación en Texinfo. Muy buena.

Hosted by www.Geocities.ws

1