¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
  1. Libros
  2. Git
  3. Escenario de desarrollador independiente
Extrait - Git Controle la gestión de sus versiones (conceptos, utilización y casos prácticos) (2a edicion)
Extractos del libro
Git Controle la gestión de sus versiones (conceptos, utilización y casos prácticos) (2a edicion) Volver a la página de compra del libro

Escenario de desarrollador independiente

Objetivo del capítulo

Este capítulo tiene por finalidad explicar cómo usar Git empleando un escenario de trabajo. En efecto, para aprender a usar Git, no se requiere necesariamente conocer todos sus comandos con la punta de los dedos: es necesario sobre todo conocer los conceptos y saber cuándo hay que ejecutar una acción concreta. Este capítulo contemplará a veces repeticiones del contenido anterior del libro. Estas pocas repeticiones permiten al lector comenzar el libro por este capítulo sin dificultad.

Este escenario es simple y concreto para explicar el funcionamiento de Git. Será, por lo tanto, teórico y práctico a la vez.

Al final de este capítulo, habrá aprendido a utilizar los principales comandos de Git con el servicio en línea Bitbucket. Será autónomo en el uso de Git, pero para usar Git en colaboración con otras personas no deje de leer el capítulo siguiente.

El repositorio resultante de este capítulo puede descargarse con los archivos de ejemplo.

Contexto del escenario

Rafael es un desarrollador web independiente. Sus servicios principales son el desarrollo de sitios web o sitios intranet específicos de la actividad del cliente. Una vez preparado un desarrollo, él asegura el mantenimiento de su aplicación. Utiliza Git desde hace varios años, lo que le permite:

  • seguir sus desarrollos y su evolución,

  • colaborar con los empleados del cliente,

  • ofrecer a sus clientes un servicio mejor terminado con un histórico completo.

Sus clientes valoran este servicio en particular porque les permite cambiar de proveedor más fácilmente si lo requieren, ya que la comprensión del desarrollo es de esta forma más sencilla.

Esto permite mostrar a sus clientes que confía en su trabajo y que no pretende impedir que vean a la competencia.

Hoy, Rafael acaba de cerrar un contrato para un nuevo cliente: el Sr. Álvarez. Recibió un pliego de condiciones que le permitirán comenzar a trabajar en el proyecto. Para las necesidades de nuestro ejemplo, este contrato va a ser muy simple, ya que consistirá en la creación de una lista de fechas de cumpleaños. En efecto, el cliente especifica en el pliego de condiciones:

«¡Estoy harto! Nunca me acuerdo del cumpleaños de mi esposa y mis hijos!»

Rafael decide comenzar sin demora el desarrollo para su cliente. Tiene la costumbre de utilizar un servicio en línea...

Creación de un repositorio

Después de haber trabajado en el diseño de su aplicación, Rafael está listo para iniciar el desarrollo real. Comenzará por crear un repositorio local en su puesto de trabajo. Abre una interfaz de línea de comandos y se ubica en la carpeta ListaCumple y ejecuta el comando siguiente:

git init 

Este comando creará un nuevo repositorio en la carpeta actual. Esto significa que Rafael podrá ahora utilizar Git y, por lo tanto, los comandos Git, dentro de este directorio.

Técnicamente, cuando se ejecuta git init, Git crea un archivo .git en la carpeta actual. Este directorio oculto incluirá todo el contenido del repositorio. En cualquier caso se debe saber que solo Git debe gestionar los archivos de este directorio. Una simple modificación en este directorio podría corromper el repositorio y evitar que funcione correctamente.

Por el momento, Rafael no ha creado ningún archivo; por lo tanto, no tiene nada que hacer. Él podrá iniciar su desarrollo.

Comienzo del desarrollo

De momento, Rafael no requiere seguir los archivos, porque todavía no tiene ninguno. Comenzará el desarrollo creando un archivo HTML llamado cumple.html en la carpeta ListaCumple, con el siguiente contenido:

<html> 
<head> 
    <title>Lista de cumpleaños</title> 
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> 
    <script type="text/javascript"  
src="static/lib/js/jscolor/jscolor.js"></script>  
</head>  
<body>  
    <h1>Lista de cumpleaños</h1>  
    <p>  
        <button onclick="javascript:lista_cump();"> 
Generar la lista</button>  
        <button onclick="javascript:localStorage.clear();"> 
Eliminar</button> 
    </p> 
   <p> 
        <br />Agregar un cumpleaños 
        <br />Persona: <input type="text" id="cump_persona" /> 
        <br />Fecha: <input type="text" id="cump_fecha" /> 
        <br...

Guardar las modificaciones

Una vez que los archivos se añaden al índice, se pueden agregar con un commit en el histórico de Git. Un commit solo debe efectuarse sobre modificaciones que representan una tarea o un trabajo concreto. Es importante recordar que Git no es un sistema de respaldo de código, sino un gestor de versiones. Los commits deben representar un cambio único que satisfará una necesidad concreta (parche de un bug, módulo de una nueva funcionalidad, etc.). No hay que pensar que un commit que solo afecta a una sola línea es inútil: si responde a una necesidad identificada con esta sola y única línea (como la corrección de una sintaxis errónea), no se debe agrupar con otras modificaciones para formar un commit mucho mayor.

Cada commit debe contener un mensaje de commit que explique el origen de los cambios. Rafael hace ahora commit de sus modificaciones con el comando git commit:

git commit -m "lista de cumpleaños y añadir en localstorage" 

Se aconseja limitar el tamaño de los mensajes a 49 caracteres. Cuando el commit es importante, y 49 caracteres no son suficientes para escribir un mensaje simple y explícito, se aconseja utilizar el editor de texto para añadir el mensaje sin utilizar el argumento -m.

Un nuevo git status indicará esta vez que ningún archivo se ha modificado desde el último commit....

Bitbucket

Cuando los desarrolladores se refieren a los servicios de alojamiento de repositorio, el principal sitio web del que hablan es GitHub, en particular gracias a los muy populares proyectos libres que alberga (el kernel de Linux, Django, Bootstrap, etc.). Sin embargo, GitHub no es el único; también existe Bitbucket, que es mucho más discreto, aunque posee muchas similitudes con GitHub.

Bitbucket es un servicio en línea que ofrece muchas funcionalidades:

  • Almacenamiento de repositorios en línea: esto permite trabajar a varias personas sobre el repositorio almacenado en Bitbucket.

  • Visualización del repositorio: la interfaz web permite tener conocimiento de las modificaciones efectuadas en el repositorio. La interfaz es clara y más agradable de usar que la línea de comandos para la consulta, ¡aunque pueda ser desconcertante para los incondicionales de la consola!

  • Red social: con un sistema de cuenta personal, se puede participar en proyectos libres. El perfil de la cuenta muestra los aportes del usuario a los proyectos.

  • Modificación en directo: si un desarrollador debe aplicar una modificación muy simple en un archivo, puede hacerlo directamente a través de la interfaz web. Bitbucket permite editar los archivos y hacer commit desde una cuenta de usuario. Por supuesto, en caso de modificaciones sustanciales es mejor pasar por el repositorio local.

Bitbucket tiene además algunas ventajas en comparación con GitHub:

  • Modelo de negocio que favorece a los trabajadores independientes y pequeñas empresas que trabajan en muchos proyectos, ya que GitHub y Bitbucket segmentan los repositorios en dos zonas: los repositorios públicos, a los que puede acceder cualquiera, y los repositorios privados, a los que puede acceder un equipo definido por el administrador del repositorio. Bitbucket favorece a los equipos pequeños, ya que no pone límite al número de repositorios privados almacenados, pero factura a los equipos de más de cinco desarrolladores en función...

Integrar un nuevo desarrollo

Después de las solicitudes de su cliente, Rafael deberá modificar la aplicación. En efecto, el cliente desea poder añadir un color de su elección para cada cumpleaños. El cliente quiere pagar lo menos posible y solicita la solución menos costosa y más simple.

Rafael modifica el archivo cumple.html de esta manera:

  • Debajo del campo fecha, agrega un campo para definir el color:

<br />Color (ej : 0F0): <input type="text" id="color" /> 
  • Modifica a continuación las funciones agreg_cump() y lista_cump() del archivo static/js/cumple.js:

function agreg_cump() { 
    cump_persona = document.querySelector('#cump_persona').value; 
    cump_fecha   = document.querySelector('#fech_cump').value; 
    color   = document.querySelector('#color').value;  
    cump= { 
        'cump_persona': cump_persona, 
        'fech_cump': fech_cump, 
        'color': color 
    };  
    nb_cump = cump_get_nb_cump();  
    localStorage.setItem(nb_cump.toString(), JSON.stringify(cump)); 
    nb_cump++;  
    localStorage.setItem('nb_cump'...

Anular las modificaciones de un archivo

Para tratar de mejorar el ejemplo de color determinado por el texto del campo color, Rafael cambia en el archivo cumple.html la línea que contiene el color del campo:

<br />Color (ej. 0F0 o 00FF00, el nombre de los colores no está 
soportado) : <input type="text" id="color" /> 

Después de haber probado esta modificación, Rafael se da cuenta de que no es realmente muy útil y que puede crear confusión. Decide, por lo tanto, eliminarla. Para esto va a utilizar el siguiente comando:

git checkout cumple.html 

Este comando permite solicitar a Git restaurar el estado del archivo cumple.htmltal como está en HEAD.

.gitignore: ignorar una librería

Cuando Rafael hace una demostración de la página web a su cliente, este le responde: «Pero esto no es práctico, ¿cómo recuerdo todos estos códigos de colores? ¿No puedo tener algo mejor y menos caro?».

Rafael le propone un campo que le permitirá seleccionar un color a partir de una paleta. El código de color se generará automáticamente a partir del color elegido. Al proponer esto, Rafael sabe que va a utilizar una librería existente que ya ha encontrado en otros desarrollos. Esto le permite garantizar un precio muy atractivo, ya que va a reutilizar un código existente.

Después de que Rafael le dé el precio, el Sr. Álvarez acepta directamente mientras murmulla algunas reticencias: «Otra factura... Si se hubiera hecho directamente...».

Después de dejar a su cliente, Rafael comienza por descargar la librería JSColor del sitio oficial (http://jscolor.com). Luego modifica el archivo cumple.html y añade la siguiente línea justo antes de la etiqueta de cierre </head>:

<script type="text/javascript" 
src="static/lib/js/jscolor/jscolor.js"></script> 

Y va a modificar la línea que contiene el campo para definir el color con el siguiente contenido:

<br />Color (ej. 0F0) : <input type="text" id="color" 
class="color"...

Hacer commit de todos los archivos añadidos o modificados

Desde el comienzo, Rafael añade los archivos uno a uno en el índice. Es una operación repetitiva, sobre todo cuando se deben añadir todos los archivos agregados o modificados.

Existe un argumento para el comando git add que permite añadir todos los archivos agregados/modificados en el índice. -A.

En primer lugar, Rafael debe verificar todos los archivos agregados/modificados con el comando git status. El comando le indica que solo el archivo cumple.html se ha modificado. Utilizando el comando siguiente, Git añadirá los archivos modificados en el índice (aquí, solo cumple.html).

git add -A 

Antes de hacer el commit, Rafael va a comprobar que el archivo no se encuentra en el índice con el comando git status. Luego hace commit de la modificación que permite elegir el color con la librería:

git commit -m "Agregar ventana opción color" 

Este comando permite ganar mucho tiempo, pero no debe impedir respetar dos reglas:

  • Hay archivos que no hay que versionar: si Rafael hubiera usado el comando git add -A antes de poder incluir el archivo .gitignore, habría versionado todos los archivos de la librería. Gracias a .gitignore, el último commit contiene solo los archivos necesarios.

  • El uso de commits atómicos: los commits deben representar una modificación independiente de las otras....

Enviar los commits al repositorio remoto

Validando sus modificaciones, Rafael añadió un commit a su repositorio local, pero de momento el repositorio remoto no tiene ninguna información sobre este último commit. Él va a enviar las modificaciones de su rama actual al repositorio remoto.

git push 

El resultado indica que el envío ha sido efectuado. Si un desarrollador es concienzudo, como Rafael, verificará a su vez en la interfaz web de Bitbucket que su commit se ha tenido debidamente en cuenta.

Mostrar las diferencias entre dos commits

Supongamos, por ejemplo, que desde hace varias semanas Rafael no ha podido trabajar en su proyecto por diversas razones (reserva de documentos del cliente, vacaciones, etc.). Para comprender de nuevo el objetivo del proyecto y lo que ya se ha hecho, consulta la lista de los commits (con git log) y decide mirar los cambios en el último commit. Para esto debe ejecutar el comando:

git diff 4702 40a42 

El identificador del último commit comienza por 40a42 y el penúltimo empieza por 4702. El comando git diff funciona especificando dos commits.

La respuesta de Git toma la forma de una lista de líneas. Las líneas eliminadas por el commit llevan como prefijo un signo - y están en rojo. Las líneas añadidas llevan como prefijo un signo + y están en verde. Las demás líneas, de color negro, rodean cada modificación.

También es posible ver los cambios introducidos por un commit directamente a partir de Bitbucket. La ventaja de utilizar la línea de comandos es que puede trabajar sin depender del cliente Git.

Clonar el repositorio remoto

Durante algunos días, Rafael va a irse de vacaciones. Él no tiene la intención de abandonar su proyecto, por lo cual se va a llevar un pequeño equipo para continuar tranquilamente. Para tener un repositorio propio y funcional, va a clonar su repositorio depósito en el equipo portátil. Para esto, necesita GIT en su equipo portátil. También necesita recuperar la URL de clonado en Bitbucket. Esa URL se encuentra en la página principal del repositorio, después de pulsar el enlace Clone del menú, como se muestra en la captura siguiente:

images/10-08.png

Luego, utilizará la interfaz de línea de comandos para situarse en la carpeta que contendrá el proyecto y usar el comando:

git clone https://rdauzon@bitbucket.org/jjolivares/ 
listaCumple.git cumpleVacaciones 

Este comando tendrá el efecto de copiar el repositorio en una nueva carpeta cumpleVacaciones. Esto significa que Rafael tiene acceso a todos los commits anteriores y a las modificaciones que contienen. Clonar un repositorio no solo corresponde a copiar el directorio de trabajo, sino a copiar todos los elementos de un repositorio.

Por otra parte, los archivos configurados en .gitignore no se han copiado. En efecto, Git los ignora por completo. Habrá que copiarlos de forma manual por el momento. Este comportamiento puede no parecer muy práctico, ya que a pesar de todo es necesario copiar manualmente...

¿Para qué sirve una rama?

Las ramas representan una de las funcionalidades más interesantes de Git. En cada repositorio Git, se encuentra una rama por defecto: la rama master. Esta rama master corresponde generalmente a la rama principal del proyecto.

Las ramas corresponden a la desviación de otra rama (como puede ser una rama de un árbol en comparación con el tronco del que sale). En otras palabras, una rama se utiliza para mantener una versión especial del proyecto para un propósito específico y fijado de antemano.

Pueden servir para:

  • desarrollar una nueva funcionalidad sin contaminar la rama superior con modificaciones no validadas,

  • guardar una rama correspondiente a una versión estable definida. Por ejemplo, un desarrollador crea una versión 1.0 de un software y no desea incorporar en ella las últimas modificaciones.

Rafael tiene ganas de ofrecer una nueva funcionalidad a su cliente: una propuesta de los colores utilizados. Es decir, que debajo del campo de texto se pueda definir el color, Rafael va a añadir botones correspondientes a los colores ya utilizados en el sitio. Cuando el usuario haga clic en uno de esos botones, el campo color se rellenará con el valor elegido. En primer lugar creará su nueva rama (en su repositorio cumpleVacaciones).

git branch color_buttons 
git checkout color_buttons 

Este comando le indicará a Git que Rafael desea...

Cambiar de rama

Rafael recibe una llamada urgente de su cliente. En efecto, no le gusta nada el título de la página. Le pide a Rafael que modifique el título, que era Lista de cumpleaños por Página de cumpleaños.

Rafael no va a realizar esta modificación en la rama que contiene los botones de colores. En efecto, el cliente puede que no acepte los botones o pedirá otra modificación antes de la puesta en producción. Rafael volverá a la rama principal (la rama por defecto de Git se llama master) para modificar el título. Para esto, utilizará el comando siguiente:

git checkout master 

Este comando permite cambiar de rama. Un cambio de rama significa que el directorio de trabajo se actualizará a partir de los datos de la rama especificada en el comando. En este caso, esto significa que las modificaciones efectuadas en la rama color_buttons serán eliminadas del directorio de trabajo, pero conservadas por Git.

Después de haber ejecutado este comando, se puede verificar la rama en la que se efectuará el próximo commit con el siguiente comando:

git branch 

Este comando muestra la salida siguiente:

  color_buttons 
* master 

Esta salida indica que hay dos ramas en el repositorio y que el estado del directorio de trabajo corresponde a la rama master.

Si Rafael consulta los archivos, ya no verá los cambios que realizó para establecer el sistema...

Fusionar dos ramas

Para hacer una demostración del sistema de botones a su cliente, Rafael se sitúa en la rama color_buttons:

git checkout color_buttons 

Recupera entonces las modificaciones que había efectuado en esta rama. Solo que no cuenta con el cambio de título que acaba de hacer en la rama master. Su cliente no va a ser estar muy dispuesto a su propuesta si no están las modificaciones solicitadas. Rafael recupera entonces las modificaciones efectuadas en la rama master empleando el comando git merge:

git merge master 

Cuando Rafael ejecuta el comando anterior, Git le propone un mensaje para el commit que va a representar las modificaciones de master que se incluirán en la rama color_buttons. Conserva este mensaje para su commit.

Este comando integrará las modificaciones de la rama master en la rama colors_buttons. Implícitamente, el comando git merge significa que las modificaciones de la rama especificada serán añadidas en la rama en la cual el repositorio está posicionado. Esta etapa de fusión genera a veces un conflicto cuando las mismas partes del archivo se han modificado en ambas ramas. Los conflictos deben ser resueltos manualmente por el desarrollador.

Después de haber hecho una demostración del sistema de botones a su cliente, este acepta la actualización para una puesta en producción. Se encuentra muy satisfecho de tener un sistema...