On Github fjordansilva / git-training
Por Fernando Jordán / @fjordansilva
En esta presentación de GIT básico veremos los siguientes puntos:
¿Qué es GIT? Historia de GIT Fundamentos de GIT Trabajar con GIT:GIT es un sistema de control de versiones. Un sistema de control de versiones registra los cambios realizados sobre un archivo o conjunto de archivos a lo largo del tiempo, de modo que se puedan recuperar versiones específicas más adelante.
GIT es una evolución de los sistemas de control de versiones actuales. Es un sistema de control de versiones distribuido. A continuación se explican los distintos tipos de sistemas y lo que significa que sea un control de versiones distribuido.GIT surge a partir de la necesidad de gestionar el código fuente del núcleo de Linux.
Durante muchos años Linux utilizó un sistema propietario denominado BitKeeper, pero Linus Torvalds decidó desarrollar un sistema propio enfocado en:
Entonces... ¿cómo trabaja GIT?
Cada vez que se confirma un cambio, GIT hace una foto del aspecto de los archivos en ese momento y guarda una referencia a esa instantánea. Los archivos no modificados no son almacenados de nuevo.
La mayoría de las operaciones en GIT sólo necesitan archivos y recursos locales para operar. Por ejemplo:
Todo en GIT es verificado mediante el checksum antes de ser almacenado, y es identificado a partir de ese momento mediante dicha suma. Esto significa que es imposible cambiar los contenidos de cualquier archivo o directorio sin que GIT lo sepa.
De hecho, de forma interna, GIT guarda todo no por el nombre del archivo, si no por el hash de dicho archivo.
Cuando realizas acciones en GIT, casi todas ellas sólo añaden información a la base de datos de GIT. Es muy difícil conseguir que el sistema haga algo que no se pueda deshacer, o que de algún modo borre información.
Esto hace que usar GIT sea muy agradable, porque sabemos que podemos experimentar sin peligro de fastidiar gravemente las cosas.
GIT tiene tres estados principales en los que se pueden encontrar tus archivos: confirmado (committed), modificado (modified), y preparado (staged).
El flujo de trabajo sería:
Modificas una serie de archivos en tu directorio de trabajo. Preparas los archivos, añadiendolos a tu área de preparación. Confirmas los cambios, lo que toma los archivos tal y como están en el área de preparación, y almacena esas instantáneas de manera permanente en tu directorio de GIT.Para empezar a trabajar con GIT necesitaremos las siguientes herramientas:
Para la generación de los certificados necesarios para la autenticación en servidores GIT utilizaremos:
Como cliente GIT utilizaremos SourceTree desarrollado por Atlassian.
Podremos trabajar con cualquier servidor GIT. Algunos de los más populares son:
Tarea que se realiza al inicio del proyecto o durante la vida del proyecto si se subdivide en distintos módulos. Como ejemplo vamos a crear un proyecto en GitLab:
La autenticación con GIT la podemos realizar de dos formas: claves SSH o mediante login/password.
La autenticación mediante claves SSH es preferible en términos de seguridad y comodidas para el usuario, ya que una vez generados los juegos de claves pública / privada e informado al servidor, el cliente SourceTree se encargará de todo lo relativo a la autenticación.
La URL del repositorio nos indica el tipo de login a realizar:
git@git.connectis-ict.es:aireuropa_casillero_digital/mod-middleware.git https://gitlab.connectis-ict.es/aireuropa_casillero_digital/mod-middleware.gitCreación de las claves SSH en Windows:
Como resultado de la creación de las claves SSH en Windows obtendremos 3 archivos:
ssh_key.pub - clave publica ssh_key.ppk - clave privada ssh_key.txt - Información de las claves para el servidor GITUna vez creadas las claves SSH, debemos informar al servidor GIT de las mismas para que nos permita el acceso:
Es la primera operación a realizar sobre un repositorio. Para obtener una copia de un repositorio existente al que se desea contribuir el comando a utilizar es clone.
Clonar significa realizar una copia de todo el contenido del repositorio que se encuentra en el servidor GIT en nuestro PC.
A diferencia de otros sistemas (SVN), se obtiene una copia completa del repositorio del servidor, de forma que se podrá trabajar sin necesidad de conexión.
mkdir git-training cd git-training git clone git@git.connectis-ict.es:fjordan/git-training.git
Se debe utilizar el botón de la barra de herramientas "Clone / New".
Tu principal herramienta para determinar qué archivos están en qué estado es el comando git status. Si ejecutas este comando justo después de clonar un repositorio, deberías ver algo así:
cd git-training git status # On branch master nothing to commit, working directory clean
Esto significa que tienes un directorio de trabajo limpio —en otras palabras, no tienes archivos bajo seguimiento y modificados—. GIT tampoco ve ningún archivo que no esté bajo seguimiento, o estaría listado ahí. Por último, el comando te dice en qué rama estás. Por ahora, esa rama siempre es "master", que es la predeterminada.
Conocer el estado de los archivos en SourceTree es muy sencillo: Una vez seleccionado el repositorio con el que queremos trabajar, tendremos dos formas de verlo:
Para empezar el seguimiento de un nuevo archivo se usa el comandogit add. Iniciaremos el seguimiento del archivo README ejecutando esto:
touch README cd git-training git add README
Si vuelves a ejecutar el comando git status, verás que tu README está ahora bajo seguimiento y preparado:
git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: README #
Para realizar el seguimiento de un archivo nuevo con SourceTree, únicamente necesitamos pulsar el botón "Add".
Esta acción añadirá todos los archivos sobre los que NO se realice seguimiento, no se podrá realizar una selección individual.
Vamos a modificar un archivo que ya estuviese bajo seguimiento. Si, por ejemplo, modificamos el archivo MiArchivo.txt que ya está bajo seguimiento, y ejecutamos el comando git status de nuevo, veremos algo así:
git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: README # # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # # modified: MiArchivo.txt #
El archivo MiArchivo.txt aparece bajo la cabecera "Modificados pero no actualizados" ("Changes not staged for commit") —esto significa que un archivo bajo seguimiento ha sido modificado en el directorio de trabajo, pero no ha sido preparado todavía—.
Para prepararlo, ejecuta el comandogit addy volvemos a ejecutar git status:
$ git add MiArchivo.txt $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: README # modified: MiArchivo.txt #
Al modificar los archivos, en SourceTree nos aparecerán como pendientes de ser enviados ( "Uncommited changes" ).
Mientras no sean enviados, la herramienta queda a la espera y va añadiendo al mismo commit todos los archivos que sean modificados.
A menudo tendrás un tipo de archivos que no quieras que GIT añada automáticamente o te muestre como no versionado. Suelen ser archivos generados automáticamente, como archivos de log, o archivos generados por tu compilador.
Para estos casos puedes crear un archivo llamado .gitignore, en el que listas los patrones de nombres que deseas que sean ignorados. por ejemplo:
$ cat .gitignore *.sh *.class target/
# un comentario – esta línea es ignorada # no permitir archivos con extensión .a *.a # autorizar el archivo lib.a, incluso aunque no se permitan los archivos .a !lib.a # ignorar el archivo TODO que está en el raíz, pero no otros (por ejemplo subdir/TODO) /TODO # ignorar todos los archivos en la carpeta build/ build/ # ignorar los archivos txt (ejemplo: doc/notes.txt) en el primer nivel de la carpeta, pero permitir doc/server/arch.txt doc/*.txt # ignorar todos los archivos .txt de la carpeta doc/ doc/**/*.txt
Para poder ignorar archivos, tenemos que modificar las propiedades del proyecto:
Ahora que el área de preparación está como tú quieres, podemos confirmar los cambios. Hay que recordar que cualquier cosa que esté sin preparar no se incluirá en la confirmación de archivos.
La forma más fácil de confirmar es escribiendogit commit -m <comentario>:
$ git commit -m "Story 182: Fix benchmarks for speed" [master]: created 463dc4f: "Fix benchmarks for speed" 2 files changed, 3 insertions(+), 0 deletions(-) create mode 100644 README
En cada commit, GIT almacena un punto de control que conserva: un puntero a la copia puntual de los contenidos, metadatos del autor y el mensaje. Con cada commit, GIT realiza una fotografía del estado actual del repositorio.
Una rama GIT es simplemente un puntero móvil apuntando a una de esas confirmaciones. La rama por defecto de Git es la rama master.Con GIT podemos crear ramas fácilmente gracias al comando:git branch <nombre>
$ git branch testingIMPORTANTE! Este comando sólo crea una nueva rama, no nos sitúa en ella. Explicar el puntero HEAD: E sun puntero que indica a GIT en que rama se encuentra el usuario en cada momento.
Para crear una rama con SourceTree, pulsaremos el botón "Branch":
Nos mostrará el diálogo de propiedades:
Más adelante veremos una forma más eficiente de trabajar con Ramas y Etiquetas gracias a GIT Flow.Para pasar de una rama a otra, utilizaremos el comandogit checkout <rama>
$ git checkout testing
A partir de este momento, cualquier commit que se realice será sobre la rama activa, en nuestro caso "testing"
$ vim test.rb $ git commit -a -m 'made a change'Explicar que estos gráficos de GIT, las flechas se leen en dirección contraria.
¿Qué sucede si ahora queremos volver a la rama anterior "master"?
$ git checkout masterExplicar que en este momento estamos "por detrás" del ultimo commit realizado y que la información enviada .
Si hacemos algún cambio sobre la rama actual... ¿donde se almacenará? ¿cómo quedará nuestro repositorio?
$ vim test.java $ git commit -a -m 'hacemos algunos cambios'
Con SourceTree podemos situarnos sobre las ramas fácilmente, pero primero tenemos que realizar un seguimiento local de la rama remota:
Tras mostrar el diálogo de confirmación del nombre de la rama, tendremos en local la rama remota y estaremos situados en ella.
Pero si ya hemos hecho en algún momento un seguimiento de la rama y queremos situarnos sobre ella, sólo tenemos que hacer doble clic sobre el nombre de la rama o seleccionar el menu contextual "Checkout branch <nombre>...".
Con GIT se pueden crear etiquetas (marcas) en puntos específicos de la historia del repositorio. Para ello utilizaremos el comando git tag. Por ejemplo, para listar las etiquetas del repositorio actual:
$ git tag v0.1 v1.3
O podemos buscar una etiqueta utilizando un patrón de búsqueda: git tag -l <:patrón>
$ git tag -l 'v1.4.2.*' v1.4.2.1 v1.4.2.2 v1.4.2.3 v1.4.2.4
Con GIT podemos crear etiquetas en nuestra rama de trabajo gracias al comando:git tag -a <nombre> -m <mensaje>
$ git tag -a v1.4 -m 'my version 1.4' $ git tag v0.1 v1.3 v1.4
Este tipo de etiquetas se denominan etiquetas anotadas, se almacenan como objetos complejos en la base de datos de GIT: tienen checksum, mensaje de etiquetado, fecha, autor, etc...
Para crear una etiqueta con SourceTree, pulsaremos el botón "Tag":
Nos mostrará el diálogo de propiedades:
Más adelante veremos una forma más eficiente de trabajar con Ramas y Etiquetas gracias a GIT Flow.Cuando se quiere compartir una rama o un conjunto de cambios con el resto del mundo, se debe enviar a un servidor remoto (push). Los cambios realizados sobre las ramas locales NO se sincronizan automáticamente con los remotos, hay que enviarlo (push) expresamente. Por ejemplo, supongamos que tenemos cambios que queremos publicar en una rama llamada "testing":git push <remoto> <rama>
$ git push origin testing Counting objects: 20, done. Compressing objects: 100% (14/14), done. Writing objects: 100% (15/15), 1.74 KiB, done. Total 15 (delta 5), reused 0 (delta 0) To git@gitlab.com:fjordan/git-training.git * [new branch] testing -> testingExplicar que en el ejemplo "origin" hace referencia al remoto principal y que puede haber más de un remoto configurado.
Para publicar los cambios con SourceTree, pulsaremos el botón "Push":
Nos mostrará el diálogo de propiedades:
Activando (checkout) una rama local a partir de una rama remota, se crea automáticamente lo que podríamos denominar "una rama de seguimiento" (tracking branch). Las ramas de seguimiento son ramas locales que tienen una relación directa con alguna rama remota.
Cuando queremos actualizar los contenidos de nuestro local con los contenidos del remoto, debemos utilizar el comando:git pull
$ git pull remote: Counting objects: 20, done. remote: Compressing objects: 100% (14/14), done. remote: Total 15 (delta 5), reused 0 (delta 0) Unpacking objects: 100% (15/15), done. From git@gitlab.com:fjordan/git-training * [new branch] serverfix -> origin/serverfixExplicar que en el ejemplo "origin" hace referencia al remoto principal y que puede haber más de un remoto configurado.
Para recuperar cambios con SourceTree, pulsaremos el botón "Pull":
Nos mostrará el diálogo de propiedades:
En el día a día, para realizar las tareas más comunes utilizaremos esta secuencia de comados sobre la rama de trabajo en curso:
Añadir cambios al repositorio:
$ git add . $ git commit -m <mensaje> $ git push origin <rama>
Obtener cambios del repositorio:
$ git pull
Con SourceTree, la secuencia de trabajo que emplearemos para compartir nuestro trabajo será:
Añadir los cambios: Confirmar los cambios: Enviar los cambios:El elemento principal de trabajo con GIT son las ramas. En ellas vamos a ir almacenando todos los elementos de nuestro proyecto: Releases, Fixes, nuevas Features, experimentos, etc. Necesitamos una forma de organizar el trabajo ordenada y que nos permite poder tener una trazabilidad y seguimiento del proyecto.
Git Flow es una extensión de GIT que facilita la gestión de ramas y flujos de trabajo.Elementos básicos en Git Flow:
Rama master: Cualquier commit que se realice sobre esta rama debe estar preparado para subir a producción. Rama develop: En esta rama estará el código que formará parte de la siguiente versión del software. Ramas auxiliares:Para activar Git Flow en el proyecto, pulsamos su botón en la barra de herramientas:
La primera vez que lo utilicemos, nos preguntará los nombres de las ramas/etiquetas a utilizar. Dejamos los valores por defecto:
Una vez configurado Git Flow, para cualquier rama o etiqueta nueva que necesitemos, al pulsar el botón nos preguntará:
Una vez finalizada la rama en la que estamos trabajando, al pulsar el botón nos preguntará:
Se utilizarán todos los tipos de ramas disponibles en Git Flow más un conjunto personalizado de etiquetas:
Rama master: Asociada al contenido actual en producción. Rama develop: Asociada a la siguiente versión del software. Ramas auxiliares:Un proyecto típico tendrá esta apariencia:
Las ramas de tipo feature tendrán las siguientes características:
Se deben originar desde la rama develop Una vez finalizadas, su código se incorporará a la rama develop Su nombre irá asociado al sistema de gestión de proyectos. Por ejemplo, una tarea en Redmine con enlace https://<dirección del servidor>/issues/5531 nos producirá una rama con nombre feature/5531Las ramas de tipo release tendrán las siguientes características:
Se deben originar desde la rama develop Una vez finalizadas, su código se incorporará a la rama develop Su nombre irá asociado a la versión del software que se publica. Se debe utlizar notación semántica de tres dígitos X.Y.Z junto al nombre de la rama. El último dígito se deja sin definir ya que en esta rama se incorporarán los fixes necesarios para que el código se pueda pasar a producción con garantías.Ejemplo: release/1.2.x
Las ramas de tipo hotfix tendrán las siguientes características:
Se deben originar desde la rama master Una vez finalizadas, su código se incorporará a la rama master (si han sido 100% verificados los cambios) o a la rama develop (si hay que realizar pruebas antes del paso a producción) Su nombre irá asociado al sistema de gestión de proyecto: Por ejemplo, una tarea en Redmine con enlace https://<dirección del servidor>/issues/5531 producirá una rama con nombre hotfix/5531Durante el ciclo de vida del proyecto, se establecerán las siguientes etiquetas para una versión X.Y.Z del proyecto:
Por Fernando Jordán / @fjordansilva