Volver

Git explicado con mis propias palabras

Imagen del slider

13 de marzo de 2018

Por J. Pisi - Desarrollador experto en SQUAD

Es muy sencillo. Primero, haz un pull del branch «master». Después, prueba, confirma y envía tus cambios indicando si se trata de una nueva funcionalidad, una corrección o una corrección de emergencia. Por último, envía tu solicitud de fusión.

Git explicado con mis propias palabras

Al terminar mi formación, me di cuenta de que Git aparecía mencionado muy a menudo en las ofertas de trabajo. Con ganas de añadir un punto más a mi currículum, me lancé a por el tutorial de Grafikart para intentar conocer un poco mejor esta herramienta. El objetivo: no quedarme completamente desorientado el día de mi incorporación. Os ofrezco algunas explicaciones sencillas y una recopilación de algunos comandos con los que uno se puede encontrar en la jungla, a veces hostil, de las herramientas de desarrollo y la organización.

¿Qué es Git?

Sí, empezamos por lo fácil. Es una herramienta de «control de versiones». Permite guardar diferentes versiones de nuestro código. En pocas palabras, es como hacer una copia de seguridad en un videojuego, sin sobrescribir sistemáticamente la última, de modo que se conserve todo el progreso. Así, si queremos volver a jugar una parte, podemos hacerlo gracias al historial. Git te permitirá visualizar este historial con precisión (para una mejor legibilidad, sé preciso y conciso al nombrar una versión).

Es lo mismo… Con un poco de imaginación.
Es lo mismo… Con un poco de imaginación.

¿Cómo se hace una copia de seguridad?

Hay varias formas de hacerlo: con una interfaz gráfica a través de GitHub, o mediante la línea de comandos en un terminal*un rayo que surca el cielo*. ¡No hay que tener miedo, vamos a por la segunda opción! Ah, y ya que estamos en la consola, ¡git help, git commit -help y git (acción) -help serán tus mejores aliados!

Lo que nos da:

  1. Después de abrir mi terminal, me desplazo a la carpeta correcta con el comando «cd» (por ejemplo: cd documentos/programación/mi-proyecto).
  2. Si aún no se ha hecho, ejecuto «git init» para indicarle a Git que debe supervisar esta carpeta (se creará un directorio).
  3. Utilizo «git add -all» para indicarle a Git que «prepare» (stage) todas las carpetas que se van a guardar.
  4.  Ya casi estamos: «git commit -m» para guardar una versión del proyecto en este momento. Aquí, «-m» permite escribir un comentario sobre el estado del proyecto.Ejemplo: git commit -m «Añadido del boletín informativo».
  5. «git status» me indica si todo va bien (por lo que conviene utilizarlo muy a menudo).
  6.  «git log –oneline» me permite ver todo el camino recorrido al mostrarme una lista de todas las confirmaciones realizadas (véase la imagen anterior).

¡Viajar en el tiempo!

TUTORIAL DE GIT
TUTORIAL DE GIT

Gracias al comando «checkout», podemos, en cierto modo, retroceder en el tiempo. La idea es la siguiente: le pedimos a Git que nos muestre cómo estaba el código en la versión -n. Si abres tu directorio y tu editor de texto tras ejecutar este comando, todo volverá a estar como estaba, pero tu trabajo no se perderá.

Cómo hacerlo:

  1.  Preparación: «git status» me indica que todo va bien y «git log –oneline» me muestra todas las confirmaciones.
  2. Yo utilizo «git checkout» + el «código» que aparece en el git log. Se trata de una secuencia de números y letras que identifica las versiones y que precede a tus comentarios. Ejemplo: «git checkout 42e9cf6». También se puede escribir «git checkout 42e9cf6 index.php» para ver solo un archivo.
  3. El «HEAD» se encuentra ahora en la confirmación deseada. ¿Qué es el HEAD? Indica el punto en el que te encuentras. Si lo comparamos con un viaje en el tiempo, es el momento en el que has aparcado tu DeLorean.
  4.  Para volver a la versión más reciente, escribe «git checkout» + «code» o «git checkout master» (volveremos sobre esta sintaxis más adelante, cuando hablemos de las ramas).

En este modo no puedes modificar el historial. Si, a pesar de todo, realizas cambios, Git no sabrá qué hacer con ellos y no se vincularán a ninguna rama.

Cambiar la historia

Así que, a partir de ahora, hay que tener cuidado. Git nos ofrece la posibilidad de modificar el historial de confirmaciones. Antes de entrar en detalles, tened muy presente que esto solo se hace a nivel local. Se puede modificar el historial por varias razones:

  • simplemente para limpiarlo y hacerlo más legible.
  • volver a una versión que funcionaba (en caso de que haya problemas).

A) Fusionar las confirmaciones

Si tengo demasiadas confirmaciones y estas no son relevantes, puedo optar por fusionar algunas de ellas mediante el rebase.

  1. Compruebo cuántas confirmaciones se ven afectadas (git log –oneline).
  2. Me sitúo en la última confirmación. (git checkout + código).
  3. «git rebase HEAD~n» (donde n representa el número de confirmaciones anteriores seleccionadas) o «git rebase HEAD^» (donde cada acento representa una confirmación anterior). Ejemplo: HEAD~3 === HEAD^^^.
  4.  Tal y como está, y si estás en Linux, el terminal pasa al modo «nano» (*otro relámpago que atraviesa el cielo*). ¡Se ve todo! Hay muchas opciones disponibles, pero lo que nos interesa es «squash». Así que solo escribiremos «squash» en lugar de «pick» en los commits que queramos integrar en la rama principal. Pulsamos |Ctrl| + |x| y nano nos pregunta qué mensaje queremos conservar. Borra, reescribe, como quieras, y vuelve a pulsar |Ctrl| + |x|.
  5. Todo ha salido bien, has vuelto al terminal y Git te informa con su prosa tan poética de lo que ha hecho.
  6.  Ha surgido un problema… Git te indicará que hay un conflicto entre las versiones (a menudo, duplicados). Tendrás que abrir tu editor de texto: Git tiene la amabilidad de resaltar las zonas en conflicto. Simplemente borra el contenido que te molesta, guarda los cambios, vuelve a ejecutar «git commit» y, por último, finaliza el proceso con «git rebase –continue».
  7.  ¡Todo va bien! «git log –oneline» para comprobar con nuestros propios ojos que todo ha salido bien.
  8. \Alerta/¡Me he perdido! «git rebase –abort» para cancelarlo todo.

B) Revert: Deshacer una confirmación

Esta función permite deshacer una confirmación, y esa anulación se registrará como una nueva confirmación… En otras palabras, deshacer una confirmación es una acción que afecta al proyecto y, como tal, queda registrada en el historial.

  1. «git log –oneline» (El Famoso).
  2. «git revert» + «código».
  3. Nano te permite editar el mensaje; pulsa |Ctrl|+|x| para confirmar.
  4. Vuelvo al terminal, ejecuto «git log» para comprobarlo y ya está solucionado.

C) El RESET

Aquí es donde empezamos a jugar con fuego, ya que las acciones que realices serán definitivas. Se requiere concentración, serenidad y reflexión. Este modo te permitirá limpiar tu historial para que resulte más legible o volver a una versión anterior. ¿Cuál es la diferencia con «revert»? Estos cambios no se registrarán en un commit que indique que se ha realizado una eliminación.

  • «git reset»: permite deshacer el último «git add». Por ahora, todo va bien.
  • «git reset –soft» + «código»: el HEAD vuelve a esa confirmación, borra todas las siguientes, pero mantiene en «stage» los cambios que hay en tu editor de texto, como si hubieras ejecutado un «git add».
  • «git reset –mixed» + «código»: modo predeterminado. Funciona igual que el programa, salvo que eres tú quien debe ejecutar el comando «git add».
  • «git reset –hard» + «código»: igual que el anterior, pero además borra todos los cambios que hayas realizado en tu editor. ¡Viajas en el tiempo hasta los 15 años y ¡pum! ¡Tienes 15 años y has olvidado todo lo que has vivido desde entonces! En otras palabras, se acabó el juego y vuelves a tu última copia de seguridad. ¡No hay que tomárselo a broma con algo que lleva «hard» en el nombre!

Bueno, bueno, ya hemos repasado los comandos principales, salvo uno. ¡El que le dará otra dimensión a tu organización! Bueno, más bien «dimensiones» sería más acertado.

«Branch»

Hasta ahora solo hemos utilizado una «rama», llamada «master». Podríamos conformarnos con ella si trabajamos solos, pero el problema es que muy pronto nos veremos desbordados por las confirmaciones. Git nos permite crear «ramas» para dar más claridad a nuestro trabajo.

¿Qué es una «branch»? Se puede traducir como sucursal o rama, como la de un árbol, pero creo que la imagen no es la más adecuada. De hecho, una vez terminado el trabajo en una «branch», se lleva de vuelta a la rama principal y se elimina la que ya no sirve. Aquí hay una bonita ilustración.

En esta imagen, no veo realmente un árbol, a lo sumo dos vías férreas que se separan y se vuelven a unir. Pero la mejor comparación es una cadena de montaje de una fábrica de coches.

Así, una «rama» sirve para desarrollar una funcionalidad concreta antes de ser eliminada, ya que la rama principal solo admite confirmaciones cuando estas corresponden a un determinado avance del proyecto.

Lo que nos da en código:

  1. «git branch» me permite ver una lista de las «ramas».
  2. «git branch» + «nombre» para crear una nueva. Ejemplo: «git branch ruedas» (en la que encontraré commits relacionados con la suspensión o los neumáticos, por ejemplo...).
  3. «git checkout» + «nombre de la rama» para mover el HEAD.
  4. Utilizar todas las funciones que hemos visto anteriormente...

Y para incorporar los cambios al master, vamos a utilizar el comando «merge»:

  1. «git checkout master» para pasar a la rama principal.
  2. «git merge» + «nombre de la rama» (en nuestro ejemplo, «ruedas»).
  3. «git branch roue -d»: así se trabaja de forma ordenada y se borra lo que ya no sirve.

Depósito a distancia

Hasta ahora hemos trabajado localmente. Git también nos permite utilizar un repositorio remoto: un «remote» (literalmente, «a distancia»). Se trata de una carpeta compartida a la que todos enviarán su trabajo (y de donde recuperarán el de los demás). Puede ser una memoria USB, una cuenta de Dropbox, otro archivo en el mismo ordenador, etc. También se pueden utilizar servicios como GitHub o Bitbucket.

Cómo funciona:

0/ Si no utilizas un servicio de terceros, tendrás que ejecutar «git init –bare» en la carpeta que servirá como repositorio remoto.

1/ «git init remote add» + «nombre del repositorio remoto» + «ruta». Para inicializar el repositorio remoto. Por convención, se llama «origin». Ejemplo: git init remote add origin url.

2/ «git remote -v» me permite ver una lista de los repositorios y «git branch -r» de las ramas remotas.

3/Supongamos que me uno a un proyecto en curso; ejecuto «git clone» + «ruta» + «nombre de la carpeta en la que se debe clonar» para recuperar todo el proyecto. Si solo quiero una parte, añado «–depth n» (donde n es el número de commits que quiero recuperar, empezando por el más reciente). Ejemplo: git clone url-sitio-de-golf –depth 4

4/ «git push» + «remote» + «branch» me permite enviar mi trabajo. Ej.: git push origin master.

«remote contiene cambios que no tienes localmente», ¡Caramba! ¡Alguien ha hecho un push antes que yo! Solo tengo que actualizarme con un simple:

4b/ «git pull –rebase origin master». Fíjate en el uso de «rebase»: sirve para fusionar de forma ordenada. Es decir, la anotación «merge of» no aparecerá en el nombre de la confirmación, lo que mejora la legibilidad. Ahora solo me queda volver a hacer el push del punto 4/.

5/ «git push origin –delete branch» me permite eliminar la rama remota una vez desarrollada la funcionalidad.

¡¡¡Uf!!!

¿Sigues ahí? ¡Bien hecho! No es fácil leer todo esto de un tirón. Espero que te haya resultado útil. Hemos repasado los conceptos básicos de la línea de comandos. Más allá de las «simples» consideraciones técnicas, Git es una herramienta de gestión y organización que se puede utilizar de varias maneras. Una de ellas es Git Flow. Tenía pensado hablar de ello, pero…

No estoy preparado…

Y eso es todo. Una última cosa sobre GitHub. Ofrece la posibilidad de realizar estas confirmaciones mediante arrastrar y soltar. Y, sobre todo, cuenta con un sistema de:

  • Incidencias: para notificar problemas.
  • Fork permite clonar el trabajo de otra persona y trabajar en él creando una nueva rama #buenasprácticas.
  •  Solicitud de incorporación para enviar la rama que acabamos de crear al responsable del proyecto.

En mi equipo utilizamos GitKraken, que ofrece una interfaz gráfica con bonitos colores para representar las diferentes ramas. Dicho esto, tener algunos conocimientos básicos de la línea de comandos, al menos para asignar un nombre a las acciones, me ha resultado muy útil.

¡Feliz programación! \o/

El tutorial de grafikart:

Créditos de la imagen @deviantart:

Redibujo de Pepe-Silvia por Cicadaqueen

Doc Emmett Brown, por ambellinaleander

Goten y Trunks, por Vegetaslittlelover