0b10

Github se lanzó en 2008. Si tu carrera de ingeniería de software, como la mía, no es más antigua que Github, entonces Git puede ser el único software de control de versiones que hayas usado. Mientras que la gente a veces se queja de su empinada curva de aprendizaje o de su interfaz intuitiva, Git se ha convertido en el lugar al que todo el mundo acude para el control de versiones. En la encuesta de desarrolladores de InStack Overflow de 2015, el 69,3% de los encuestados usó Git,casi el doble de los que usaron el segundo sistema de control de versiones más popular, Subversion.1 Después de 2015, Stack Overflow dejó de preguntar a los desarrolladores sobre los sistemas de control de versiones que utilizan, quizás porque Git se había vuelto tan popular que la pregunta no era interesante.

El propio Git no es mucho más antiguo que Github. Linus Torvalds lanzó la primera versión de Git en 2005. Aunque hoy en día los desarrolladores más jóvenes podrían tener dificultades para concebir un mundo en el que el término «software de control de versiones» no solo significaba Git, tal mundo existía no hace mucho tiempo. Había muchas alternativas para elegir. Los desarrolladores de código abierto preferían Subversion, las empresas y las compañías de videojuegos usaban Perforce (algunas todavía lo hacen), mientras que el proyecto del núcleo de Linux se basó en un sistema de control de versiones llamado BitKeeper.

Algunos de estos sistemas, en particular BitKeeper, pueden resultar familiares para un usuario joven transportado en el tiempo. La mayoría no lo haría. Dejando a un lado BitKeeper, los sistemas de control de versiones anteriores a Git funcionaban de acuerdo con un paradigma fundamentalmente diferente. En una taxonomía ofrecida por Eric Sink, autor de VersionControl by Example, Git es un sistema de control de versiones de tercera generación, mientras que la mayoría de los predecesores de Git, los sistemas populares en la década de 1990 y principios de la década de 2000,son sistemas de control de versiones de segunda generación.2 Donde se distribuyen los sistemas de control de versiones de tercera generación, se centralizan los sistemas de control de versiones de segunda generación. Es casi seguro que has escuchado anteriormente a Git descrito como un sistema de control de versiones» distribuido». Nunca entendí del todo la distinción entre distribución y centralización, al menos no hasta que instalé y experimenté con un sistema de control de versiones centralizado de segunda generación.

El sistema que instalé fue CVS. CVS, abreviatura de Concurrent Versions System, fue el primer sistema de control de versiones de segunda generación. También fue el sistema de control de versiones más popular durante aproximadamente una década hasta que fue reemplazado en 2000 por Subversion. Incluso entonces, Subversion se suponía que era «CVS pero mejor», lo que solo subraya cuán dominantes se habían vuelto los CVS a lo largo de la década de 1990.

CVS fue desarrollado por primera vez en 1986 por un científico informático holandés llamado Dick Grune,que buscaba una forma de colaborar con sus alumnos en un proyecto de compilación.3 CVS era inicialmente poco más que una colección de RCS (Revision Control System), un sistema de control de versiones de primera generación que Grune quería mejorar. RCS funciona de acuerdo con un modelo de bloqueo pesimista, lo que significa que no hay dos programadores que puedan trabajar en un solo archivo una vez. Para editar un archivo, primero debe pedirle a RCS un bloqueo exclusivo en el archivo, que conservará hasta que termine de editarlo. Si alguien más ya está editando un archivo que necesita editar, tiene que esperar. CVS mejoró los RCSY marcó el comienzo de la segunda generación de sistemas de control de versiones al cambiar el modelo de bloqueo pesimista por uno optimista. Los programadores ahora podían editar el mismo archivo al mismo tiempo, fusionando sus ediciones y resolviendo más tarde cualquier conflicto. (Brian Berliner, un ingeniero que más tarde se hizo cargo del proyecto CVS, escribió un documento muy legible sobre las innovaciones de CVS en 1990.)

En ese sentido, CVS no era tan diferente de Git, que también funciona de acuerdo con un modelo optimista. Pero ahí es donde terminan las similitudes. De hecho, cuando Linus Torvalds estaba desarrollando Git, uno de sus principios rectores era WWCVSND, o «Lo que CVS No Haría».»Siempre que tenía dudas sobre una decisión,se esforzaba por elegir la opción que no había sido elegida en el diseño de los vehículos.4 Por lo tanto, aunque CVS es anterior a Git por más de una década, influyó en Git como una plantilla negativa.

He disfrutado mucho jugando con CVS. Creo que no hay mejor manera de entender por qué la naturaleza distribuida de Git es una mejora con respecto a lo que había antes. Así que los invito a que vengan conmigo en un viaje emocionante y gasten los próximos diez minutos de su vida aprendiendo sobre una pieza de softwarenobody que ha utilizado en la última década. (Ver corrección.)

Introducción a CVS

Las instrucciones para instalar CVS se pueden encontrar en la página principal del proyecto. En macOS, puede instalar CVS usando Homebrew.

Dado que CVS está centralizado, distingue entre el universo del lado del cliente y el universo del lado del servidor de una manera que algo como Git no lo hace. La distinción no es tan pronunciada que haya diferentes ejecutables. Pero para comenzar a usar CVS, incluso en su propia máquina, tendrá que configurar el motor de CVS.

El motor CVS, el almacén central de todo su código, se llama repositorio.Mientras que en Git normalmente tendrías un repositorio para cada proyecto, en CVS el repositorio contiene todos tus proyectos. Hay un repositorio central para todo, aunque hay formas de trabajar solo con un proyecto a la vez.

Para crear un repositorio local, ejecute el comando init. Harías esto en algún lugar global, como tu directorio personal.

$ cvs -d ~/sandbox init

CVS permite pasar opciones para el cvs comando en sí o a lainit subcomando. Las opciones que aparecen después del comando cvs son globales, mientras que las opciones que aparecen después del subcomando son específicas del comando sub. En este caso, el indicador -d es global. Aquí le dice a CVS dónde queremos crear nuestro repositorio, pero en general el indicador -d apunta a la ubicación del repositorio que queremos usar para cualquier acción dada. Puede ser mejor suministrar la bandera -d todo el tiempo, por lo que se puede establecer la variable de entorno CVSROOT en su lugar.

Ya que estamos trabajando localmente, acabamos de pasar una ruta para nuestro argumento -d, pero también podríamos haber incluido un nombre de host.

El comando crea un directorio llamado sandbox en su directorio personal. Si enumera el contenido de sandbox, encontrará que contiene otro directorio llamado CVSROOT. Este directorio, que no debe confundirse con el variable de entorno, contiene archivos administrativos para el repositorio.

¡Felicitaciones! Acaba de crear su primer repositorio CVS.

Código de verificación

Digamos que has decidido mantener una lista de tus colores favoritos. Eres una persona con inclinación artística pero extremadamente olvidadiza. Escribe tu listadel colores y guardarlo como un archivo llamado favorites.txt:

blueorangegreendefinitely not yellow

supongamos también que usted ha guardado el archivo en un nuevo directorio llamadocolors. Ahora le gustaría poner su lista de colores favoritos bajo control de versiones, porque dentro de cincuenta años será interesante mirar hacia atrás y ver cómo sus gustos cambiaron con el tiempo.

Para hacer eso, tendrá que importar su directorio como un nuevo CVSproject. Puede hacerlo utilizando el comando import :

$ cvs -d ~/sandbox import -m "" colors colors initialN colors/favorites.txtNo conflicts created by this import

Aquí estamos especificando la ubicación de nuestro repositorio con el -d flagagain. Los argumentos restantes se pasan al subcomando import. Tenemos que proporcionar un mensaje, pero aquí realmente no lo necesitamos, así que lo dejamos en blanco. El siguiente argumento, colors, especifica el nombre de nuestro nuevo directorio en el repositorio; aquí acabamos de usar el mismo nombre que el directorio en el que estamos.Los dos últimos argumentos especifican la etiqueta vendor y la etiqueta release respectivamente.Hablaremos más sobre etiquetas en un minuto.

Acaba de introducir su proyecto «colores» en el repositorio CVS. Existen varias maneras de introducir código en CVS, pero este es el método recomendado por Pragmatic Version Control usando CVS, el libro de programación pragmática sobre CVS. Lo que hace que este método sea un poco incómodo es que tienes que revisar tu trabajo fresco, a pesar de que ya tienes un directorio colors. En lugar de usar ese directorio, vas a eliminarlo y luego ver la versión que CVS ya conoce:

$ cvs -d ~/sandbox co colorscvs checkout: Updating colorsU colors/favorites.txt

de Este modo se creará un nuevo directorio, también llamado colors. En este directorio encontrará su archivo original favorites.txt junto con un directorio llamadoCVS. El directorio CVS es básicamente el equivalente de CVS al directorio .git en cada repositorio Git.

Hacer cambios

Prepárate para un viaje.

Al igual que Git, CVS tiene un subcomando status:

Aquí es donde las cosas comienzan a parecer extrañas. CVS no tiene objetos de confirmación. En lo anterior, hay algo llamado «Identificador de confirmación», pero esto podría ser solo una edición relativamente reciente: no aparece ninguna mención de un» Identificador de confirmación » en Control de versiones de Programación mediante CVS, que se publicó en 2003. (lastupdate to CVS fue lanzado en 2008.5)

Mientras que con Git hablarías de la versión de un archivo asociado con commit45de392, en CVS los archivos se versionan por separado. La primera versión de yourfile es la versión 1.1, la siguiente es la versión 1.2, y así sucesivamente. Cuando se involucran ramas, se agregan números adicionales, por lo que puede terminar con algo como 1.1.1.1 anterior, que parece ser el predeterminado en nuestro caso, aunque no hayamos creado ninguna rama.

Si se ejecuta cvs log (equivalente a git log) en un proyecto con lotsof ficheros y se compromete, quieres ver una historia individual para cada archivo. Puede tener un archivo en la versión 1.2 y un archivo en la versión 1.14 en el mismo proyecto.

Sigamos adelante y hagamos un cambio a la versión 1.1 de nuestro archivo favorites.txt :

 blue orange green+cyan definitely not yellow

Una vez realizado el cambio, podemos ejecutar cvs diff para ver lo que CVS piensa que hemos hecho:

CVS reconoce que hemos agregado una nueva línea que contiene el color» cian » al archivo. (En realidad, dice que hemos hecho cambios en el archivo» RCS»; puedes ver que los CVS nunca escaparon por completo de su asociación original con RCS.) La diferencia que se muestra es la diferencia entre la copia de favorites.txt en nuestro directorio de trabajo y la versión 1.1.1.1 almacenada en el repositorio.

Para actualizar la versión almacenada en el repositorio, tenemos que confirmar el cambio. En Git, esto sería un proceso de varios pasos. Tendríamos que organizar el cambio para que aparezca en nuestro índice. Luego nos comprometimos a hacer el cambio. Finalmente, para que el cambio sea visible para cualquier otra persona, tendríamos que enviar la confirmación al repositorio de origen.

En CVS, todas estas cosas suceden cuando se ejecuta cvs commit. CVS simplemente reúne todos los cambios que puede encontrar y los coloca en el repositorio:

Estoy tan acostumbrado a Git que esto me parece aterrador. Sin la oportunidad de realizar cambios de escenario, cualquier cosa antigua que hayas tocado en tu director de trabajo podría terminar como parte del repositorio público. ¿Escribiste de forma pasiva y agresiva la función mal implementada de un compañero de trabajo por necesidad catártica, sin pretender que lo supiera? Lástima, ahora cree que eres un idiota. Tampoco puedes editar tus commits antes de enviarlos, ya que un commit es un push. ¿Disfruta de pasar 40 minutos ejecutando repetidamente git rebase -i hasta que su historial de compromisos locales fluya como la derivación de una prueba matemática? Lo siento, no puedes hacer eso aquí, y todo el mundo va a descubrir que en realidad no escribes tus pruebas primero.

Pero ahora también entiendo por qué a tanta gente le resulta innecesariamente complicado Git.Si cvs commit es a lo que estabas acostumbrado, entonces estoy seguro de que los cambios de puesta en escena y empuje te parecerán una tarea inútil.

Cuando la gente habla de que Git es un sistema «distribuido», esta es principalmente la diferencia a la que se refieren. En CVS, no puedes hacer confirmaciones localmente. Un commit es un envío de código al repositorio central, por lo que no es algo que puedas realizar sin conexión. Todo lo que tienes localmente es tu directorio de trabajo. En Git, tienes un repositorio local completo, por lo que puedes realizar confirmaciones durante todo el día, incluso mientras estás desconectado. Y puedes editar esas confirmaciones, revertir, ramificar y seleccionar cherry tanto como quieras, sin que nadie más tenga que saberlo.

Dado que las confirmaciones eran más importantes, los usuarios de CVS a menudo las hacían con poca frecuencia.Las confirmaciones contendrían tantos cambios como hoy en día podríamos esperar ver en la solicitud de extracción de aten-commit. Esto era especialmente cierto si las confirmaciones activaban un CIbuild y un conjunto de pruebas automatizado.

Si ahora ejecutamos cvs status, podemos ver que tenemos una nueva versión de nuestro archivo:

Fusionando

Como se mencionó anteriormente, en CVS puede editar un archivo que otra persona ya esté editando. Esa fue la gran mejora de CVS en RCS. ¿Qué sucede cuando necesitas recomponer tus cambios?

Digamos que has invitado a algunos amigos a añadir sus colores favoritos a tu lista. Mientras agregan sus colores, usted decide que ya no le gusta el color verde y lo elimina de la lista.

Cuando vaya a confirmar sus cambios, es posible que descubra que CVS nota un problema:

Parece que sus amigos confirmaron sus cambios primero. Por lo tanto, su versión defavorites.txt no está actualizada con la versión del repositorio. Si ejecuta cvs status, verá que su copia local de favorites.txt es la versión 1.2 con algunos cambios locales, pero la versión del repositorio es 1.3:

Puedes ejecutar cvs diff para ver exactamente cuáles son las diferencias entre 1.2 y 1.3:

Parece que a nuestros amigos les gusta mucho el rosa. En cualquier caso, han editado una parte diferente del archivo de la que tenemos nosotros, por lo que los cambios son fáciles de combinar. CVScan hacer eso por nosotros en el momento de ejecutar cvs update, que es similar a git pull:

$ cvs updatecvs update: Updating .RCS file: /Users/sinclairtarget/sandbox/colors/favorites.txt,vretrieving revision 1.2retrieving revision 1.3Merging differences between 1.2 and 1.3 into favorites.txtM favorites.txt

Si usted echa un vistazo a favorites.txt, usted encontrará que se ha beenmodified para incluir los cambios que tus amigos realizados en el archivo. Tus cambios siguen ahí también. Ahora eres libre de confirmar el archivo:

El resultado final es lo que obtendrías en Git ejecutando git pull --rebase. Tus cambios se han añadido encima de los cambios de tus amigos. No hay un «compromiso de fusión».»

A veces, los cambios en el mismo archivo pueden ser incompatibles. Si tus amigos hubieran cambiado de «verde» a «oliva», por ejemplo, eso habría entrado en conflicto con que tu cambio eliminara «verde» por completo. En los primeros días de CVS, este era exactamente el tipo de caso que causaba que la gente se preocupara de que CVS no fuera seguro; El bloqueo pesimista de RCS garantizaba que tal caso nunca pudiera surgir. Pero CVS garantiza la seguridad asegurándose de que los cambios de nadie se sobrescriban automáticamente. Tienes que decirle a CVS qué cambio quieres seguir adelante, de modo que cuando ejecutes cvs update, CVS marca el archivo con ambos cambios de la misma manera que Git lo hace cuando detecta un conflicto de fusión. A continuación, debe editar manualmente el archivo y elegir el cambio que desea conservar.

Lo interesante a tener en cuenta aquí es que los conflictos de fusión deben solucionarse antes de que pueda confirmar. Esta es otra consecuencia de la centralización de CVS nature.In Git, no tienes que preocuparte por resolver fusiones hasta que envíes los compromisos que tienes localmente.

Etiquetas y ramas

Dado que CVS no tiene objetos de confirmación fácilmente direccionables, la única manera de obtener una colección de cambios en grupo es marcar un estado de directorio de trabajo en particular con atag.

Crear una etiqueta es fácil:

$ cvs tag VERSION_1_0cvs tag: Tagging .T favorites.txt

Más tarde podrá devolver archivos a este estado ejecutando cvs update y pasando la etiqueta a -r bandera:

$ cvs update -r VERSION_1_0cvs update: Updating .U favorites.txt

Debido a que necesita una etiqueta para rebobinar a un estado de directorio de trabajo anterior, CV fomenta una gran cantidad de etiquetas preventivas. Por ejemplo, antes de los refactores principales, puede crear una etiqueta BEFORE_REFACTOR_01 que podría usar más adelante si el factor no funciona correctamente. Las personas también usaban etiquetas si querían generar diferencias en todo el proyecto. Básicamente, todas las cosas que hacemos rutinariamente hoy con los commithash deben anticiparse y planificarse con CVS, ya que necesitaba tener las etiquetas disponibles ya.

Las ramas se pueden crear en CVS, más o menos. Las ramas son solo un tipo especial de etiqueta:

$ cvs rtag -b TRY_EXPERIMENTAL_THING colorscvs rtag: Tagging colors

Que solo crea la rama (a la vista de todos, por cierto), por lo que aún debe cambiar a ella usandocvs update:

$ cvs update -r TRY_EXPERIMENTAL_THING

Los comandos anteriores cambian a la nueva rama en su directorio de trabajo actual, pero el Control de versiones pragmático Usando CVS en realidad aconseja que cree un nuevo directorio para contener su nueva rama. Presumiblemente, sus autores encontraron que cambiar directorios era más fácil que cambiar ramas en CVS.

El Control de versiones pragmático Utilizando CVS también desaconseja la creación de ramificaciones de una rama existente. Recomiendan crear solo ramas fuera de la rama principal, que en Git se conoce como master. En general, la ramificación se consideraba una habilidad CVS «avanzada». En Git, puede iniciar una nueva rama por casi cualquier razón trivial, pero en CVS, la ramificación se solía usar solo cuando era realmente necesario, como para las versiones.

Una rama se podría fusionar de nuevo en la línea principal utilizando cvs update y la bandera -j :

$ cvs update -j TRY_EXPERIMENTAL_THING

Gracias por la confirmación Historias

En 2007, Linus Torvalds dio atalk sobre Git en Google. Git era muy nuevo entonces, por lo que la charla fue básicamente un intento de persuadir a una sala llena de programadores escépticos de que debían usar Git, a pesar de que Git era tan diferente de todo lo que entonces estaba disponible. Si aún no has visto la charla, te animo a verla. Linus es un orador entretenido, incluso si Henever no es su atrevido yo. Hace un excelente trabajo explicando por qué el modelo distribuido de control de versiones es mejor que el centralizado. Gran parte de sus críticas están reservadas para CVS en particular.

Git es una herramienta compleja. Aprenderlo puede ser una experiencia interesante. Pero también me asombran continuamente las cosas que Gitcan hacer. En comparación, CVS es simple y directo, aunque a menudo no es posible realizar muchas de las operaciones que ahora damos por sentadas. Volver atrás y usar CVS por un tiempo es una excelente manera de encontrarse con una nueva apreciación del poder y la flexibilidad de forGit. Ilustra bien por qué comprender el historial de desarrollo de software puede ser tan beneficioso: recoger y reexaminar herramientas de observación le enseñará volúmenes sobre el por qué detrás de las herramientas que usamos hoy en día.

Si te ha gustado este post, más como sale cada cuatro semanas! Sigue a @ TwoBitHistory en Twitter o suscríbete al feed RSS para asegurarte de saber cuándo sale una nueva publicación.

Corrección

Me han dicho que hay muchas organizaciones, en particular organizaciones de riesgo adverso que hacen cosas como hacer software para dispositivos médicos, que aún usan vehículos electrónicos. Los programadores de estas organizaciones han desarrollado pequeños trucos para sortear las limitaciones de CVS, como crear una nueva rama para casi todos los cambios para evitar comprometerse directamente con HEAD. (Gracias a Michael Kohne por señalar esto.)

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *