 Muy buenas tardes a todos y bienvenidos a esta última jornada de charlas de esta workout que nos está enamorando a todos. Estamos aquí en una tarde repleta de charlas maravillosas con Jesús Famíeiro y vamos a decir unas cositas de él. Veréis, existen dos formas de cocinar, acabamos de comer, os lo digo. La que se hace por puro trámite es a de que se hace con receta simple y para pasar, sale de el paso y la creativa en la que te centras en los detalles para el pasito más allá, para delitarse los urmets. Igual que con las formas de cocinar con jit podemos hacer lo básico para salir del paso, como crear un repositorio, clonarlo, realizar un cómic, hacer ramas de desarrollo, un pull, un push, ese tipo de cosas. Podemos centrarnos en los pequeños detalles urmets que nos permitirán sacarle el máximo partido allí. Pues en esta sesión Jesús, están en el otro lado, nos va a explicar unos cuantos conceptos avanzados para cocinar ese entorno. Jesús Famíeiro es ingeniero de telecomunicación y se define como un artesano de jit y supongo que de cocina, de lasti. Trabaja como director técnico en cuadralia y le cedo la palabra para que nos deleite con su receta de jit. Bueno, muchas gracias Mr. Rón. Muchas gracias antes de nada a la organización por haber seleccionado mi charla y por todo el trabajo que están haciendo que creo que eso he visto una parte muy pequeña de todo lo que están haciendo y es muchísimo el trabajo. Gracias a todos nosotros por estar aquí, me ocurro un montón de cosas más interesantes que asistir en una charla de jit un viernes por la tarde, pese a que estemos confinados o semi confinados, pero bueno, voy a intentar hacerlo lo más amenaposible para que aprendamos lo máximo posible en este rato que tenemos aquí. Como ya acaba de entrar a Mr. Rón, esta charla, es una charla de introductoria en que vamos a dar unas pequeñas pinceradas a jit, esta charla se trata de aprender una serie de conceptos, una serie de tips, de funcionalidades que nos permitirán exprimir lo máximo, sacar lo máximo de jit. Antes nada me presento, yo soy Jesús Amiero, esta charla podéis ahora mismo descargarla, el pdf que vais a poder ver, la podéis descargar desde mi blog, desde jesusamiro.com, por lo tanto os aconsejo que atendáis a la charla, que no copies nada, porque está todo disponible ya ahora mismo online. ¿Quién soy? Bueno, como acaba de decir Mr. Rón, soy Jesús Amiero, ingeniero de telecomunicación, trabajo de director técnico en Quadralia, una pequeña empresa en la zona de Vigo que nos dedicamos fundamentalmente a temas de comercio electrónico con magento y con WordPress, también nos dedicamos al desarrollo de aplicaciones web a medida, para aplicaciones empresariales, y comercializamos SaaS de desarrollo propio, fundamentalmente uno que tenemos con bastante éxito, que se llama Clínicas Cloud. Además, como proyectos, como setprojects, como proyectos laterales, tengo uno que puede ser interesante a toda la gente que asiste a una work online que se llama la semana PHP.com, que es una lista de correo que se publica todos los martes a las 8 de la mañana, con contenido de diversos sobre PHP, WordPress, Laravel, Symphony, Drupal, pero casi en la mitad del contenido que publico está relacionado con WordPress. Por lo tanto, quizá que, si te dedicas a WordPress, sea interesante su contenido y, por lo tanto, puede que te interese suscribirte. Una vez finalizada la introducción, lo que vamos a ver son los distintos puntos que vamos a ver en esta presentación. Van a ser 9 puntos. El primer punto, voy a hacer una muy breve introducción a Git para aquella gente que no conoce a Git, aunque no es recomendable asistir a esta presentación si no conoces Git de nada. Y los 8 restantes puntos van a ser una explicación concreta de una funcionalidad concreta o funcionalidades. Y lo que voy a tratar de hacer es acotar los ejemplos con ejemplos que no estén vinculados, que no estén relacionados de tal forma, que si te pierdes en alguno de los ejemplos, no pasa nada, puedes volver a verlo en la presentación que estará colgada en WordPress TV y lo que haces es poste con unas pilas y atiendes al siguiente, ¿vale? Están totalmente desvinculados. OK, entonces vamos a empezar. ¿Qué es Git? Bueno, Git simplemente es un sistema de control de versiones. Está forgingado y está pensado para realizar control de versiones de software de archivos de texto plano, pero lo podemos utilizar en un montón de sistemas mayores. ¿Vale? ¿Qué pasa que nosotros estamos centralizados en texto plano, en fricheros? La característica principal de Git es que es un sistema de control de versiones distribuido. ¿Qué quiero decir con esto? Quiero decir que toda la información que tenemos del repositorio del proyecto y de la evolución del proyecto está distribuido entre las distintas ordenadores de la gente que trabaja en el proyecto. Por ejemplo, en esta diapositiva podéis ver que tenemos tres equipos, tres desarrolladores en el proyecto, y cada desarrollador en su equipo local va a tener los distintos cómics, la evolución, la disponibilidad temporal de todo el proyecto. Además, tenemos un servidor, que puede ser un servidor propio de la empresa, puede estar en un SAS, como puede ser GitHub o Bitbucket, donde colaboramos, es decir, donde publicamos la información que tenemos en nuestro equipo para que otro compañero la pueda utilizar o viceversa publica la información para que nosotros podamos utilizarla. Esta es una distinción muy importante respecto a otros sistemas de control de versiones, como pueden ser de subn, el que se utiliza ahora mismo en WordPress.org, porque para un WordPress.org en subn, los cómics se realizan en un servidor centralizado, es decir, tenemos que tener conexión de red. Y para trabajar con un guide, no necesitamos conexión de red, lo podemos hacer casi todo, excepto colaborar en nuestro equipo local. OK, en un conocimiento de control de versiones, el elemento fundamental de la información es el cómics, que fundamentalmente lo que es es una fotografía, una instantánea, que lo que hacemos es guardamos determinados ficheros que capturamos en esa instantánea en una base de datos, en una base de datos que es el propio repositorio, guide. Otro elemento muy importante que lo veréis por todos lados cuando utilizáis guide es un conjunto de 160 bits, es decir, 20 bytes que están en una notación saldecimal, que es una función S1, S1 es una función criptográfica, que a partir de una determinada información que nosotros queremos respaldar en el repositorio, lo que hace es, calcula, les he echado uno de esos elementos y los almacena en el repositorio junto al resultado de la función. Porque esto es importante, porque lo que hace esta función es que no podamos modificar sin alterar la línea temporal, todo nuestros repositorios deciden si hacemos un cambio, ese S1 va a variar y, por lo tanto, cualquier sistema lo detectaría. Bueno, como podéis ver, la evolución temporal que tenemos en guide o cualquier otro sistema de control de versiones, realizamos un primer commit, que está, como podéis ver, caracterizado por su S1 en formato corto, son los siete caracteres. A continuación realizamos un segundo commit, que tiene como padre el commit 1. Y a continuación realizamos un tercer commit, que tiene como padre el commit 2. Y así vamos evolucionando temporalmente. Guide tiene tres zonas muy importantes donde vamos a trabajar. Tiene el director de trabajo, que está en nuestro propio ordenador y es lo que visualizamos con la línea de comandos, con nuestro video, con un editor de textos, ¿vale? Es la zona donde trabajamos directamente. Después tiene una zona intermedia que se llama zona de preparación, donde nosotros enviamos los ficheros a esa zona de preparación en un paso previo al commit. Y una vez que tenemos claro lo que queremos enviar al repositorio, pues lo que hacemos es que movemos esa información desde la zona de preparación al repositorio mediante un commit. Si en un momento queremos sacar información desde el repositorio al director de trabajo, lo haremos con un check out. Por lo tanto, ¿cómo podrá estar un fichero? Bueno, un fichero dentro de un proyecto que tengamos. En un inicio está sin seguimiento por parte de vídeo. Tenemos que poner bajo seguimiento, añadiéndolo. Y a partir de ahí, una vez que se encuentra conseguimiento, podrá estar sin modificación. Es decir, en las tres zonas de Git, el contenido será el mismo, podrá estar modificado. Es decir, hay una diferencia entre nuestra zona de trabajo y el resto de zonas, podrá estar preparado. Es decir, lo enviamos en las modificaciones a la zona de preparación en un paso previo al commit y podrá estar, otra vez, sin modificación, cuando lo enviamos al repositorio mediante un commit. Estas son las tres zonas y cómo jugamos con ellas enviando la información, los ficheros de un lado para otro. OK. Algo muy, muy importante de Git, de trabajar con Git y que utilizaremos todos los días, es el trabajo con RAMAS. El trabajo con RAMAS simplemente es, a partir de un comidio determinado, establecemos una bifurcación o un camino diverso para varios fines. Por ejemplo, en este caso, como podéis ver, tenemos la rama masta en la rama que se crea por defecto. Cuando queramos un directorio de Git, tenemos un primero commit, un primer commit. Tenemos un segundo commit y, a partir de ese segundo commit, el desarrollador creó una rama de pruebas. En esa rama de pruebas, realizó un tercer commit, un cuarto commit y, a continuación, se volvió a cambiar. A la rama master hizo un quinto commit y es como hasta ahora mismo. Veis a mayores que hay un elemento muy importante que se llama GAT que simplemente es un puntero que apunta normalmente al último commit de la rama activa, ¿vale? Si estuvimos trabajando, en este momento estamos en la rama activa, en la rama master. Si en un momento determinado nos queremos cambiar a la rama de pruebas, pues lo que tenemos es utilizar el comando de cambio de rama y, automáticamente, GAT pasará a apuntar al último commit de la rama de pruebas. Vale, todo lo que hagamos de ver hasta ahora lo puedo hacer en local en mi equipo sin ningún tipo de conexión a internet. Esto es muy importante porque podéis trabajar en cualquier lado del mundo sin necesitar una conexión para poder colaborar. Además, si queremos colaborar con otros miembros de nuestro equipo, queremos publicar software en GitHub o cualquier repositorio público, tenemos fundamentalmente 5 comandos que vamos a utilizar para interactuar con servidores. El primer de comando es GitClone. Clone es simplemente lo que va a hacer es ir a un repositorio remoto y aclonar, es decir, traer una imagen completa de ese repositorio y colocarla en mi equipo. El segundo comando GitRemote lo que me permite es definir los repositorios remotos con los que quiero trabajar, modificarlos, alterarlos, borrarlos, porque no tengo por qué colaborar con un único repositorio remoto. Puedo que esté leyendo de un repositorio concreto en el que no tengo permisos para poder guardar información, pero sí que tengo otro segundo repositorio en el que me interesa y en el que tengo permisos para guardar información. Es algo muy típico cuando colaboramos en proyectos libres con GitHub. El tercer comando es GitPush, que lo que hago es directamente enviar información desde mi ordenador, desde mi equipo local hacia el servidor. El cuarto comando es un comando inverso. Lo que hace es GitFace traer información desde el servidor remoto hasta una ramas locales que se llaman ramas de seguimiento. Todavía no fusiona la información con mis ramas locales. Elemento que sí que hace el quinto comando GitPull, lo que hace es traer esa información del servidor de remotos, los almacena en las ramas de seguimiento y a su vez las fusionas, es decir, mete la información en las ramas locales, en las que podemos trabajar nosotros con la línea de comandos. OK. Hasta aquí, la otra introducción a Git, ¿vale? A partir de aquí vamos a ir viendo los 8 puntos. Los 8 comandos, funcionalidades distintas de Git. El primer comando que vamos a ver es GitReset. Este comando es un comando muy sencillo y para que nos vale, pues nos vale para restablecer una o varias de las tres zonas que acabamos de ver antes, la zona de trabajo, la zona de preparación. O el repositorio a un comit previo. Por lo que nos puede interesar, pues por ejemplo, porque hemos realizado dos comits que nos interesa descartar, pues, por ejemplo, con un GitReset de una forma de terminada, en este caso dejar, pues sí que lo vamos a poder hacer. Hay tres tipos de GitReset. Hay un GitReset de tipo SOG que se lo va a modificar la información en el repositorio. Hay un GitReset misses que va a modificar la información en el repositorio y en la zona de preparación. Y el hard que es el más destructivo que nos borra información en las tres zonas de trabajo, ¿vale? En el último comando que vamos a ver veremos cómo poder, si metemos la pata y si borramos información con este último comando, cómo podemos recuperarla. Vamos a empezar a ver un ejemplo de GitReset SOG. Y para este ejemplo vamos a partir de algo muy, muy sencillo. Un repositorio donde tengo dos comits, en cada comit se ha añadido una línea al archivo 1. Véis que el primer comit es el que tienes hecho 145. Añado línea 1 al archivo 1.txt. Y el segundo comit es el 8e8, que es donde añado una línea 2 al archivo 1.txt. Para ejecutar un GitReset en esta situación de tipo SOG, pues lo único que hago es ejecutar el comando GitReset, pasando el parámetro menos menos SOG, y referenciando el comit previo con hegeat virgulilla 1. Este hegeat virgulilla 1 lo que hace referencia al comit previo, al comit padre, al hegeat. Si pusiera un 2, pues haría referencia al abuelo y así sucesivamente me iría moviendo en la línea temporal. Una vez que tengo juzgado este comando, si ejecuto un GitStatus, veis que lo que me dice es, mira, en la rama master, que es la única que tengo, hay cambios que están preparados para ser comiteados. Es decir, hay cambios de la zona de trabajo que fueron metidos en la zona de preparación, pero que todavía no están en el repositorio. Vamos a ver qué significa eso. Si yo compruebo el contenido de mi zona de trabajo con catarchivo 1.txt, veis que en la zona de trabajo no me ha eliminado nada. Tengo las dos líneas de los comits previos. Si ahora lo que hago es un div, un div es un comando que simplemente me establece diferencias entre determinadas zonas o entre determinados comits. En este caso, GitDiv lo que hace es una diferencia entre la zona de trabajo y la zona de preparación. El resultado es vacío, porque la zona de trabajo y la zona de preparación no han sido modificadas. Sin embargo, si hago un GitDiv entre la zona de preparación y el GAP, es decir, el último comit de repositorio, me va a decir que, mira, sí que hay una línea 2 que se ha añadido a mayores, porque es la línea que se acaba de borrar con el GitReset en el comando que acabo de ejecutar. Sí, es sencillo. Es decir, este comando GitReset es soft, lo que me va a hacer es solo modificar el contenido del repositorio. Si ejecuto el comando GitReset, pero con un ResetMixet, lo que va a hacer es modificar el repositorio y también esa zona intermedia de esa zona de preparación. La forma de invocar el comando es la misma, es GitReset, menos-mixet, indicándole el comit previo. Pero fijaros que, si ahora vuelvo a ejecutar un GitStatus, ya no me dice que los cambios están listos para ser comitados en la zona de preparación o no. Me dice, los cambios no han sido estallados, es decir, no han sido enviados todavía a la zona de preparación para ser comitados, porque hay un cambio en mi zona de trabajo que todavía no ha sido llevado a la zona de preparación ni al repositorio. Vamos a verlo ahora con los GIPs que se entienden mucho más sencillo, mucho más fácil. Vale, lo vemos aquí muy sencillo. Si comprobo el contenido de mi zona de trabajo, veis que sigo manteniendo las dos líneas. Línea 1 de archivo txt y línea 2 de archivo txt. Sin embargo, si hago un div en la zona de trabajo y la de preparación, veis que me parece ya esa línea 2. ¿Qué quiero decir esto? Que la zona de trabajo se mantiene, pero la zona de preparación ha sido borrado. Y si hago el div entre la zona de preparación y el GAD actual, me parece resultado vacío, porque tanto en la zona de preparación como en la zona en el repositorio, en el GAD, esta segunda línea ha sido borrada. Por lo tanto, este comando, el GID Reset Mixed, lo que hace es eliminar tanto la zona de preparación como en el repositorio. Y la que seguramente utilicéis de una forma más habitual, porque es la que la mayoría de gente utiliza cuando metemos la pata o hicimos trabajo, hicimos unos cuantos commits y no nos quedamos para nada, porque nos hemos equivocado, tomamos otra estrategia distinta en el trabajo, es el GID Reset Hard. Este GID Reset Hard, como ya os anticipé, nos va a borrar información entre las tres zonas de trabajo. Vamos a ver cómo sería el ejemplo. Lo primero que haría sería juntar el comando GID Reset, veis con el parámetro menos menos Hard, y lo mismo, lo vinculo al commit anterior al padre del último commit de introducción del repositorio. Si ahora un GID Status me dice, no hay nada para ser comitéado, y el arbol del trabajo está limpio. ¿Qué significa esto? Significa que el contenido de mi zona de trabajo, de preparación y el repositorio contienen la misma información, porque no hay ninguna modificación entre esas tres zonas que estemos preparando para comitéar. Ahora, si comprobo el contenido del archivo 1.txt, veis que la línea 2 desapareció, porque sí que se ha restablecido también en la zona de trabajo de esa zona anterior, y se hago los tips. Tanto en la zona de trabajo, entre la zona de trabajo y la zona de preparación, como entre la zona de preparación y el GID Actual, veis que el resultado me da vacío, porque el contenido es el mismo entre la zona de trabajo y la zona de preparación, y entre la zona de preparación y el GID Actual. Este comando es muy, muy útil para eso. Cuando metéis la pata, cuando hay commits que nos interesa nos interesa mantener, o incluso algún tipo como el SOP o el Mixed, cuando, por ejemplo, queréis borrar algún commit para no perder el trabajo en vuestra zona de trabajo. Es interesante que conozcáis. Estos son los conceptos para poder jugar con ellos de forma adecuada. El siguiente comando que vamos a ver es Cherry Peak. El Cherry Peak es un comando muy útil, y básicamente lo que me va a permitir es mover información de copiar, perdón, no mover copiar, información de commits entre distintas ramas. Es algo muy tibio, por ejemplo, yo me pongo a trabajar y hago commits en una rama y dentro de dos o tres commits me doy cuenta de que esos commits no tenían que estar en esa rama, que tenían que estar en otra rama, o que, por ejemplo, hay un commit particular que me quiero llevar a otra rama, por lo que sea. Por ejemplo, me quiero llevar un fichero guitín 9 de una rama de feature a la rama master. 40,000 casos se nos pueden pasar. Bueno, pues este comando precisamente es para realizar eso. Fijaros en este ejemplo. Aquí partimos de una rama master, que tiene dos commits, el commit 1 y el commit 2. A partir de ese segundo commit, cree una rama feature 1, que tiene el commit 3 y el commit 4. En un momento determinado, me cambié a la rama master y hice un commit 5. Y ahora me volví otra vez a la rama feature 1, ves que es la activa, porque es la que tienes. Si yo quisiera llevar este commit, el 456, a mi rama master, pues simplemente lo que tendría que hacer es situarme en la rama master, en la rama donde quiero recibir los cambios, y con el comando kitscherepeak, indicarle el sh1 de los commits que quiero traerme a esa rama. Algo tan sencillo, como veis aquí, git checkout master, que me cambia la rama activa a la rama master, y a partir de ahí, con el comando kitscherepeak y sh1, me traería ese commit a la otra rama. Quedaría algo como podéis ver en este diagrama temporal. Introduciría este commit a mayores con la información del commit 4 en la rama master y veis que el sh1 no lo mantiene, porque no lo mantiene a pesar de tener la información, porque hay bastantes elementos que varían, por ejemplo, el momento temporal, o también el commit padre, porque el sh1 se utiliza para no perder esa robustez que nos da a tener commits padre. Pero el contenido que llevó a la rama master sí que es el mismo. Vamos a verlo con un ejemplo básico. Y fijaros, el ejemplo del que parto va a tener una línea temporal muy, muy sencilla. Tengo en la rama master añadí el archivo 1 y el archivo 2. A partir del segundo commit, creé una rama de funcionalidad donde añadí un fichero guitting nore, un fichero 3, un fichero 4. Me cambié a la rama master y ahí añadí un fichero 5. Pues por lo que sea, este guitting nore me interesa llevarlo a la rama master. Lo tengo que hacer con hicherepeak. ¿Cómo lo hago? Bueno, pues muy sencillo. Me cambio a la rama master, que como podéis ver, aquí era la rama activa, porque es a la que apunta el y no tengo que cambiarme esa rama. Y hago hicherepeak y de dónde lo hago. Lo hago de un commit determinado. Lo obtengo con git reparse de este commit concreto. No es el segundo antecesor del último commit de la rama. Con este comando obtengo el s1 de ese commit concreto. Y si ahora con este comando git.log, con estos parámetros vuelvo a visualizar mi línea temporal, lo que me sale es este commit. Que fue llevado a partir después, a continuación, del último commit de rama master. Veis que el mensaje del commit es el mismo. Y lo que cambió, obviamente, como os acabo de comentar, es el s1 de este commit. Es la forma de llevar. Por ejemplo, un caso muy sencillo, este fichero quitting nore, que no existe en la rama master, a la rama master. Con este comando puedo hacer un montón de cosas a mayores. Por ejemplo, puede que me interese llevar dos o más commits a mi rama master o a otra rama. ¿Cómo lo hago? Pues es tan sencillo como ejecutar git commit e ir añadiendo uno detrás de otro los s1 en formato corto de los commits que quiero llevar a esa rama. Así es sencillo. Puede que me interese editar el mensaje del commit antes de comitearlo. Porque me interesa aclarar que lo traigo de otra rama o por lo que sea. Esto lo hago con el parámetro-c, que me va a permitir, me va a preguntar qué le indique nuevo mensaje de commit. Y a partir de cuando lo guarde, ya lo comiteará. Y también algo muy interesante que es el ejemplo que vamos a ver a continuación es cómo aplicar el contenido sin hacer commit. ¿Por qué puede ser esto interesante? Pues mira, puede ser muy interesante porque en un commit determinado puedo tener conviteados cambios en 5 archivos. Pero me puede interesar llevar solo uno o dos commits a la rama concreta. Entonces, lo que voy a hacer es llevar esos commits de una rama a otra, sin comitear, borro los archivos que no me interesa y, a partir de ahí, vuelvo a comitear. Vamos a ver cómo es el ejemplo. En este ejemplo es el mismo ejemplo que teníamos antes. Y ahora lo que me va a interesar es dejar el fichero 4 y dejar el fichero 4 y no llevar el fichero 3. Lo primero que voy a hacer es con git cherrypick y minus n, que es el parámetro que tengo que hacer para no comitearlo. Menos n significa no commit. Le voy a indicar que me lleve el último commit de la rama funcionalidad y el pen último, que son fichero 4, añado fichero 4 y añado fichero 3. Con este comando me voy a abrir esos dos commits, pero no me los va a comitear. Si ahora aún me testa tus, si los comiteara me diría que te está todo limpio, pero no va a ser el caso. Me dice, mira, en la rama master hay dos cambios listos para comitear. Hay dos archivos que se acaban de crear, archivo 3 y archivo 4. Pero a mí solo me interesa por lo que sea, llevar a la rama master uno de estos dos archivos. Entonces lo que hago es con el comando git restore y menos menos stage, que como podéis ver, os lo indica aquí el git status como podéis hacer para quitarlo de la zona de preparación. Le indico, git restore y menos menos stage, el archivo 3.xt, lo que estoy diciendo, lo estoy quitando de la zona de preparación donde me lo había dejado el git cherrypick. Y si ahora vuelvo a hacer un git status, veis que ya solo me indica, hay un nuevo archivo listo para ser comitado, ya está en la zona de preparación. Y como el archivo 3 nunca había estado en esta rama master, me dice que es un archivo un tracker. Nunca ha sido traqueado, nunca ha sido registrado o seguido por git en la rama master. Por lo tanto ahora, simplemente lo que puedo hacer, lo que tengo que hacer es borrarlo con el comando rem de nuestra línea de comandos, rm archivo 3.xt. Vuelvo a hacer el git status y veis que me sigue apareciendo este archivo 4 preparado para ser comiteado. Y lo que hago es lo comiteo, git comit, minus m para indicarle el mensaje de comit. Añado pichero 4.xt. Y cuando vuelvo a ver mi línea temporal, lo que me va a aparecer es a continuación del último comit que tenía antes de hacer el cherrypick en mi rama master, este nuevo comit. Añado pichero 4.xt. Este quizá que sea un ejemplo un poco forzado, pero que tenéis que tener claro es que el cherrypick nos permite llevar comits de una rama a otra y antes de comitaros, antes de guardarlos en el repositorio en esa rama, nos permite limpiarlos, nos permite jugar con el comit, ¿vale? Es un comando, una funcionalidad muy, muy interesante, pues para cuando metemos la pata o cuando necesitamos mover elementos entre ramas. Otra funcionalidad muy, muy interesante es el git status. El git status me permite, es un cajón desastre, una zona donde me permite meter elementos que no están guardados. Os voy a poner en situación. Imagínanos que yo hice una salida de producción este lunes, una vez que acabé de mi salida de producción está todo funcionando, me puse en una rama de feature, una rama de funcionalidad a realizar un trabajo nuevo. Y ahora mismo, en un viernes a las 4 y cuarto de la tarde, me llama el cliente y me dice, mira, tengo el comercio electrónico con un problema por la salida de producción que hicimos el lunes pasado. Automáticamente tengo que parar el trabajo con el que estoy en la rama de funcionalidad y tengo que resolver ese problema, ese bug, para poder sacarlo a producción lo antes posible, para evitar que pierda, que no trabajen, que pierda de vender todo el fin de semana. Entonces lo que voy a hacer es, mirad, antes estás almacenar esos cambios que no tengo comitéados en esa zona y ponerme a trabajar en mi rama master y una vez que acabe volver a mi rama de feature, a mi rama de funcionalidad y recuperar esa información. Vamos a verlo todo con un ejemplo. Vale, el ejemplo me acabo de anticipar con todo lo que os voy a contar, a lo que tenemos aquí. Veis que tenemos una rama master donde he comitéado el archivo 1 y el archivo 2. Y a partir de ahí, imagino que esa es mi salida a producción de lunes, tengo tres commits más, añado Gittinor, añado Fichero 3 y añado Fichero 4, que es donde estoy ahora mismo trabajando antes de que el cliente levante el teléfono y me diga que hay un error en producción. Vale, si yo ahora mismo hago un status, me dice que hay un archivo modificado. Es decir, hay un archivo que está modificado en mi zona de preparación, que todavía, perdón, en mi zona de trabajo, que no envíe todavía a la zona de preparación para comitéar y tengo que ver con eso. A mí, obviamente, no me va a interesar perder trabajo, porque si yo ahora mismo lo que trato es de cambiarme de rama, como podéis ver, aquí con Gittinor me dice que hay cambios en el archivo 4 que todavía no están ni comitéados ni metidos en el status, que es lo que vamos a ver ahora mismo, que tengo que tomar una decisión o perder la información o almacenarla en esa pila para poder cambiarme a la rama master. Entonces, lo que hago directamente es Gittin status. Con este comando, lo que me va a almacenar es los cambios que tengo en mi zona de trabajo, en mi working directory, me los almacena en esa pila y ya me permite cambiarme a mi rama master. Ahora, si hago un Gittin status, veis que me dice en la rama funcionalidad 1, no hay nada preparado para comitéar y la zona de trabajo, el arroz de trabajo está limpio. Quiero decir esto, que el contenido de las tres zonas de la de trabajo, la de preparación y el repositorio es el mismo. Entonces, en este momento, así que me permitiría cambiarme a la rama master. ¿Por qué? Porque acabo de meter esas modificaciones en el status. Si utilizo el comando Gittin status list, como podéis ver el segundo comando que tenemos en esta presentación, lo que me va a sacar es un listado con todos los elementos que he almacenado en el status. Y cómo se referencian con status? Arroba, llave, cero, llave. El siguiente elemento sería llave 1, llave 2. Y así es como los tenemos referenciados univocamente para en cualquier momento poder jugar con ellos, sacarlos o moverlos con una rama concreta. Una vez que tengo esto, ahora sí que Gittin me permite a mi rama master, Gitt checa un master. Y imagina, los que estas tres líneas que tengo a mayor es que es añadir una línea 1 de archivo 5, archivo 5. Gittada de date y commit, Gitt commit, añadiendo el fichero 253, es mi resolución al bufis en la rama master, ¿vale? Es algo muy sencillo, pero tampoco interesante que me meta ahí en un detalle a mayores. Lo que tenéis claro es que acabo de añadir un commit match en mi rama master. Ahora lo que tendría que hacer es pasar el sistema de preproducción y de ahí contraantes el sistema de producción para que el comercio electrónico deje de perder dinero por el bus que acabo de introducir. OK, tengo comitéado mi resolución en la rama master y ahora ya puedo seguir trabajando, son las 5 de la tarde, dentro un poco y ya sigo trabajando en mi rama de funcionalidad, lo que hago es, por lo tanto, me cambio de mi rama master a mi rama de funcionalidad 1. Y lo que tengo que hacer es obviamente recuperar esa información que probablemente había agorado en el STAS a mi rama funcionalidad 1. ¿Cómo lo hago? Tengo varias formas de hacerlo. Si utilizo el comando que veáis en blanco, GitStars Pop, pasándole como parámetro el identificador unívoco que me muestra el GitStars List, estás a roba, llave, cero, llave, lo que voy a hacer es recuperar ese elemento del STAS y borrarlo. Lo podría recuperar con el comando GitStars Apply el que veis en la segunda línea. Este comando lo que hace es lo recupera, pero no lo borra del STAS por si quiero aplicarlo en otro elemento determinado por el tema de cómo esté trabajando en ese momento. OK. Esto sería la salida del comando. GitStars Pop, estás a roba, llave, cero, llave. Y veis que me dice, en la rama funcionalidad 1 hay cambios que no están enviados a la zona de preparación para comitear. Es decir, me las mete directamente en mi zona de trabajo. Es decir, vuelvo a estar como estaba en el momento en el cliente levantó el teléfono y me dijo que había un bug en producción. Es muy, muy interesante para no perder trabajo y no poder ejecutar lo que tenemos que hacer en un momento determinado de una forma bastante rápida. El siguiente comando que vamos a ver se llama GitVisit. Vamos a ver, os pongo en situación. Imagínalos que tenéis un bug en un proyecto determinado y que no tenéis ni idea de dónde se ha introducido ese bug. Simplemente sabéis que hay un commit en el que sabemos que el bug está, hay un commit en el que sabemos que el bug no está y lo que nos va a permitir visit es ir apotando de forma repetitiva el intervalo hasta llegar al comit exacto donde está el bug. Vale, para mostrar este ejemplo lo que voy a hacer es un proyecto que hay en GitHub, vais a ver la URL ahora mismo que está pensado precisamente para documentar este comando. Básicamente es un proyecto muy, muy simple, un proyecto web donde tenemos un botón de menos y un botón de más. Si hago clic en el botón de menos el número se decrementa una unidad, si hago clic en el botón de más el número se incrementa una unidad. Pero no tengo ni idea por qué en un momento determinado se ha introducido un error y cuando hago clic en el botón más el número se decrementa una unidad y así sucesivamente. Por lo tanto, lo que voy a hacer con GitVisit es buscar el commit donde se ha introducido ese error para poder ver cuál es el error. Lo ideal en la consulta que os voy a explicar es que no lo tenga que hacer manualmente, que lo tuviera integrado al GitVisit con algún sistema de pruebas de forma automática, ¿vale? Pero eso es la que da fuera del alcance de esta presentación y aquí lo que voy a hacer es explicarlo de forma manual. Lo primero que voy a hacer es clamar el repositorio que os acabo de contar. GitClone, la URL del repositorio, que es un repositorio público en GitHub, y automáticamente con lo que me va a crear es un directorio que se llama visetercise. Lo que hago es, como el comando CD acedo al interior de ese directorio, tengo el repositorio con todo su historia. Esto es un elemento muy interesante de Git que me permite descargar, por defecto, descarga toda la historia del repositorio que clonamos. ¿Vale? Voy a hacer lo siguiente. Con el comando GitList, menos, menos, para nígual a 0 GR, lo que voy a obtener es el primer commit del repositorio, ¿vale? Esto es interesante porque sé que, en ese commit concreto, la funcionalidad funcionaba correctamente. En el commit que tiene, se ha hecho 1, 4, de 8, 3. Y además sé que en el Git, en último commit, en el commit que está donde apunta el GIT, el proyecto funciona incorrectamente. Por lo tanto, son mis dos parámetros de entrada. ¿Cómo utilizo este comando GitViset? Bueno, pues lo primero que hago es, me pongo en modo viset con GitVisetStart, y le digo, mira, el commit al que apunta GIT es incorrecto. Lo hago con GitVisetBadGIT, y sé que el commit donde, el primer commit del repositorio es correcto. Entonces le digo, mira, GitVisetGOOT, 4, de 8, 3, ese primer commit es correcto. Y ahí, automáticamente, lo que hace GitViset es va, a partir de ese intervalo de 5 commits que tenemos, va haciendo intervalos de la mitad del tamaño, el siguiente sería 50 commits, el siguiente de 25, el siguiente de 12, y así hasta llegar justo al commit donde está el error. En este caso, con 7 repeticiones de este comando, vamos a llegar al commit donde está, donde funciona mal. Entonces, lo que hace, como podéis ver aquí la salida de GitViset, me dice, quedan 50 revisiones. Se cambia automáticamente al commit 96c49. Es decir, está como un modo desacoplado donde el commit actual pasa desde 52 y eno el 100 al que apunta GIT hace un momento. Vale. En ese momento, lo que tengo que hacer es pulsar el F5 y hacer clic en el botón más y en el botón menos para comprobar si el proyecto está funcionando correctamente. En este caso funciona correctamente, por lo cual le digo, GitVisetGOOT, desde el 100 en ese commit concreto que acabas de posicionar, el proyecto funciona correctamente. No tenemos el GOOT. Entonces, lo que hace Git pasa de ese intervalo de 50 commits o un intervalo más pequeño de 25 commits. Vuelvo a hacer lo mismo. F5, comprobar si los botones de más y de menos funcionan o no funcionan. Y en este caso, le digo, GitVisetBad, es decir, en el commit en el que te acabas de posicionar, el proyecto funciona incorrectamente. Y así lo voy haciendo con unas cuantas ejecuciones más. La siguiente ejecución ya sería BAD. Sólo me quedaría en 5 commits. Y hasta que llegó un commit determinado, en el que le digo, GitVisetGOOT, y automáticamente me salta con un commit determinado. Me dice, mira, lo que me viene a decir la salida es, en este commit es donde has introducido el error. Quedaros con este S1 de 4789, porque lo vamos a utilizar a posteriori en otro comando. Es el commit 64. Esto simplemente es el mensaje de error, nada más. Y lo que tenemos es, se han introducido tres líneas y se han borrado tres líneas. Es lo que me saca esta información. Pues lo siguiente que hago es un GitShow de ese commit concreto, con el comando GitShow y el S1 en formato y como podéis ver, aquí claramente me está sacando el error que tengo en ese commit concreto. Si os fijáis, en esta línea se ha cambiado DEC, que está en rojo, es decir, se ha borrado, por un DC. Y en esta segunda línea se ha cambiado un INC por un IC. Es decir, esto está tarde aunque han sido cambiados, lo que produce es que un Javascript funciona de forma incorrecta y, por lo tanto, cuando hago click en el botón más, se decrementa una unidad. Así es sencillo. Esta línea también ha sido cambiada porque en cada commit se va incrementando el texto de la versión en una unidad, pero para efectos prácticos de resolver el bug no lo necesito. Vale. Y ahora ya simplemente me queda salir de este modo desacoplado para que Git vuelva a apuntar al GIT. Mediante, un Git biset, Reset, me sale de este modo biset y ya me va a arjear. ¿Qué tengo que hacer ahora? Bueno, pues ahora tengo que resolver el bug, obviamente. ¿En dónde? Depende. Veíamos que el commit era el commit 64. Tengo que ver si entre commit 64 y el commit 7, que es el último que tengo ahora mismo, tengo alguna rama que no haya sido mergeada en esta misma rama o puedo que haya sacado esa información a otras ramas que lleven ese error. Entonces tendré que resolver también esas ramas o directamente en el commit 100. Eso ya depende de cada casuística en particular. Siguiente que vamos a ver. La funcionar blame. La funcionar blame es una funcionar muy, muy sencilla. Y lo único que me va a dar es información de qué introdujo un cambio en un commit determinado, en qué commit se introdujo, qué información se introdujo, etcétera, etcétera. Vamos a verlo. Si yo ejecuto Git blame sobre el index del ejemplo anterior, veis que me va a línea por línea y me indica en qué commit se introdujo esa línea, la persona que lo hizo y la fecha y la hora. Así, aparentemente, esto quizá que no nos dé demás de información y el número de línea. 1, 2, 3, 4, veis que la saca de forma consecutiva. Aparentemente, esto no me va a valer demasiado porque tengo que ir con la barra espaciadora consultando pantalla a pantalla y es demasiada información para poder visualizarla de una forma interesante. Sin embargo, si vuelvo a visualizar el commit que tenía previamente con Git Show y su S1, donde tenía el error, veis que aquí me indica que, mira, entre la línea 67 y las 12 siguientes, es donde está el error. Realmente, donde está el error es en las 9 primeras. Lo podía acotar a esas 9 primeras. Entonces, si visualizo esas 9 líneas, me va a sacar información de qué han introducido en el error. Obviamente, esta información también la puedo ver aquí en el autor del commit. Veis que si le indicó Git blame entre las líneas 67, 76 del archivo index, me va a sacar toda la información de esas líneas en concreto. Y podéis ver que en la línea 771, donde se han introducido los errores, lo ha hecho Brad Daly en el commit B478, el día 22 del 12 a las 1341. Me saca información más fina sobre ese commit y sobre todo quién fue el último en cometer en esa línea concreta, en ese fichero concreto. El siguiente comando muy, muy interesante es el Git rebase. Antes de introducir el comando Git rebase, lo que voy a explicar son las estrategias de fusión de Git. Vamos a ver. Normalmente, como ya os comenté, cuando trabajamos con Git, lo que hacemos es trabajamos en varias ramas. Tenemos unas ramas que suelen estar vigentes al lado del proyecto, como es una rama master, una rama de develop. Y tenemos otras ramas que se llaman ramas tópicas, que están pensadas para resolver un buffish, crear una funcionalidad o elementos así, que se crea en un momento terminado o se trabaja con ellas y se fusiona su información. Se lleva su información. Hay esas ramas de master o rama de develop y las ramas les aparecen. Eso que tiene sentido para no tener un lío tremendo con un montón de ramas. La Git, para fusionar la información entre dos ramas, utiliza dos estrategias básicas. La primera estrategia se llama Fast Forward. Es una estrategia muy sencilla y esta estrategia se realiza cuando hay un camino continuo, un camino común, entre la rama sobre la que queremos finalizar la fusion y la queremos fusionar. Imagínanos, por ejemplo, en esta línea temporal muy, muy sencilla, que en la rama master tengo dos commits, los dos primeros commits. Y a partir del segundo commit he creado un tercer y un cuarto commit en la rama funcionalidad 1. Si ahora quiero llevar esta información de la rama funcionalidad 1 a la rama master, hacer es muy sencillo, es situarme en la rama master y con el comando bitmerge tener la información. Como hay un camino común, una línea común que puede seguir git, la rama master, la rama master pues simplemente va a avanzar el puntero G2 commits y automáticamente está fusionando la información. Lo hago como se acabo de comentar. Gitmerge funcionalidad 1 ya estaba previamente en la rama master. Y como podéis ver me dice, el merge se realiza mediante Fast Forward, mediante avanzando, en este caso, 12 commits. Y veis que hay dos archivos que han cambiado con dos inserciones. Porque son los archivos 3 y archivos 4 que había introducido en la rama funcionalidad 1 que viene ahora a la rama master. Y el resultado sería este. G atapuntando la rama master que a su vez está en el mismo commit que la rama funcionalidad 1. Ahora simplemente lo que haría si la funcionalidad 1 está acabada, borraré esta rama. La segunda forma que tengo de fusionar información entre ramas en Git es la forma de fusionar recursiva. Esta seda, cuando no tenemos una línea temporal continua, sino que Git tiene que buscar un antecesor común entre las otras ramas y a partir de ahí, realiza automáticamente la fusion. Es este caso en el que veis que, además de los 4 commits que tenía previamente, he añadido en la rama master un quinto commit, donde he añadido el fichero 5.xt. Si yo ahora quiero llevar el contenido de funcionalidad 1 a la rama master, no lo puedo hacer por un camino común. Sino que lo que va a hacer Git es venir hasta el segundo commit, hasta este commit predecesor de ambas ramas, va a ver qué cambios se han producido en la rama funcionalidad 1 y va a llevar esos cambios a la rama master mediante un commit de fusion, un commit de enmerge. Es decir, va a añadir un nuevo commit para esto. Como lo hago luego de la misma forma que en el caso anterior a través de la nía comandos me situo en la rama master en la que ya estaba, y le digo gitmerge con funcionalidad 1. Veis que ya no indica que ese enmerge, esa fusion, la hace mediante fast forward, sino que la realiza mediante una estrategia recursiva. Pero lo que va a hacer es lo mismo. Va a añadirle el archivo 3 y el archivo 4 con esas dos inserciones a la rama master. Veis que añade un commit a mayores, que se llama por decir un to merge branch de funcionalidad 1. Es decir, añade un commit más. La línea temporal empieza a insuciarse un poco. Me podéis decir, va, son un commit a mayores, 5, 6 commits, tampoco pasa nada. Pero qué pasa cuando colaboramos con un montón de gente, nos podemos encontrar casuísticas como esta, que ensucian enormemente nuestra línea temporal. Ensucian y, sobre todo, lo que nos hace es que si tenemos que visualizar determinada información más adelante, es arduo buscarla. Para evitar todo esto, lo que voy a utilizar es el rebase. El rebase es un concepto muy, muy sencillo, que, partiendo de la casuística anterior, lo que va a hacer, en vez de crear un commit de fusión, lo que va a llevar son el commit, el primer y segundo commit, los dos commits de la rama funcionalidad 1, justo después del último commit de la rama master. Es decir, los va a situar a continuación. Lo que tengo que hacer es poner en la rama desde la que quiero hacer el rebase e indicarle la rama que quiero rebasar. En este caso, lo que hago es un bit checkout a funcionalidad 1, es decir, a la rama desde donde quiero realizar el rebase. Y lo que le indico mediante kit rebase master es, mira, desde la rama funcionalidad 1, rebásame la rama master. Ejecuta ese rebase. Y lo que va a hacer es, como podéis ver, el último commit de mi rama master era este, pues a partir de ese commit acaba de añadir el fichero 3 y el fichero 4. Actualmente la rama activa es la funcionalidad 1, porque al hacer el rebase lo hago desde la rama desde la que quiero rebasar. Y ahora lo único que me quedaría es cambiarme a la rama master y hacer una fusión, en este caso, mediante fast forward, porque tengo una línea temporal. Pues muy sencillo, me cambió la rama master mediante kit checkout master y mediante kit merge funcionalidad 1, mediante un merge de fast forward. Lo que tengo es esos cambios fusionados en la rama master. Como podéis ver, ya tengo una línea temporal y ya empieza a ensuciarse menos mi línea temporal. El siguiente comando que vamos a ver, el kit squash, y todo lo que tiene relacionado kit squash, lo que me va a permitir es todavía limpiar más esta línea temporal, porque como podéis ver, fichero 3 y fichero 4 están dentro de funcionalidad 1, y posiblemente lo que me interesa es fusionar esos dos commits e único commit para ensuciar menos todavía mi línea temporal. Como os acabo de comentar, eso lo voy a hacer con el comando kit squash. Voy a partir de un ejemplo parecido, pero no igual, a los que ya hemos visto hasta ahora. Voy a explicarlo. Rama master añado el archivo 1 y el archivo 2. En ese momento creo una segunda rama, una rama funcionalidad 1, en la que, como primer commit, le digo, inicio la funcionalidad 1, añado fichero 3. En el siguiente commit, añado fichero 4. En el siguiente commit, añado kit ignore. Y en la rama master tengo también, además, un fichero 5.xt. Veis que la rama activa ahora mismo es la rama funcionalidad 1. Fernando, queda una magia. Hola, ¿me oyes? Sí. Queda muy poquito, un minutito, un minutito todo hoy. Venga, lo explico todo esto muy rápido. Es muy bien. Simplemente lo que tengo que hacer es mediante un revés de tipo interactivo, lo que voy a hacer es compactar estos 3 commits en un único commit y llevarlos a la rama master. ¿Cómo lo hago? Con el comando kit revés de forma interactiva, indicándole el antecesor donde quiero rebasar, es decir, indicándole este commit, que es el GAD, GAD-1, menos 2, menos 3, ¿vale? Y automáticamente revés se pone en modo interactivo. En este caso, me abre el bin y me dice, mira, aquí están los 3 commits temporalmente puestos. El primero aparece al principio, segundo y tercero. Y lo que voy a hacer es, si guardara la misma, no me haría nada, pero lo que voy a hacer ahora mismo es decirle, mira, este quiero mantenerlo y cambiarle su mensaje de commit. Por lo tanto, lo que voy a hacer es un reward, usar este commit, pero editar el mensaje de commit. Y los siguientes, lo que voy a hacer es descartar su mensaje de commit y fusionarlos con el anterior, con el primero. Entonces, en vez de un squash, lo que voy a utilizar es este comando, fissup. ¿Cómo quedaría? Pues veis que cambio este peak por este reward, este fissup y este fissup. Automáticamente guardo este contenido y como el reward necesito que introduzca un mensaje de commit, lo que hago es, me vuelvan a aparecer otra ventana de bin, y lo que le indico es el mensaje de commit para ya la fusion de los 3 commits. Inicio, bueno, esto es el que aparece por efecto, y cambiaste el mensaje por, añado la funcionalidad 1, un mensaje que es común a los 3 commits. Dejo una línea en blanco y a partir de ahí, puedo escribir lo que me de la gana, lo que me interese, para qué, para añadir a continuación, para poder visualizar en un futuro, para saber lo que hice en esta rama. Cuando salga de aquí, lo que me va a quedar esos 3 commits fusionados en este único commit, con un mensaje de commit cambiado. Y ahora lo único que me queda es hacer un rebase sobre la rama master y un merge con fast forward. Lo que hago es, ya estoy en la rama desde que quiero rebasar, hago un rebase de la rama master, veis cómo me queda, ese commit me queda a continuación de la rama master, y ahora simplemente me tengo que cambiar a la rama master y checao master y fusionar la rama funcionalidad 1 en la rama master. Con lo que ya me quedaría, como podéis ver, esos commit cambios integrados. Y lo que me queda, con un git branch menos de, es borrar la rama de funcionalidad 1, porque en ese momento ya está completa, y no me interesa temer ahí más historias. Como podéis ver, este git squash y los comandos que tienen vinculados, me permite reescribir mi línea temporal de una forma muy interesante para evitar temer unas líneas temporales que sean un auténtico inferno. Pensadlo, no ahora, pensadlo que tenéis que hacer comprobaciones dentro de tres meses o dos años. Que proyectos que se alargan muchísimo en el tiempo. Bueno, como me comenta, me hace rompo que se me acaba el tiempo, dejamos aquí la presentación, solo me quedaba un comando que era el git reflog. Lo podemos comentar si queréis en la siguiente sala, en Zoom, que me voy a estar allí la siguiente hora. Y ahora quedó a disposición vuestro para las preguntas. Jolines, qué rabia que no hayas terminado. Está todo estupendo. Tenías enamorado a todos los que estaban viendo la charla, la verdad. Bueno, pues nada, unas preguntitas. La primera de Fernando García Rebolledo. Buenas tardes. Pregunta para Jesús. Creo que eres tú. ¿Con qué recomiendas borrar cómics? Reset, rebase o cherry pick? Pues, como gallego, te voy a contestar. Depende. Y depende por la casuística. Es decir, depende. Vamos a ver si, por ejemplo, tengo unos cambios en local. Dice dos cómics. Y quiero cargármelos directamente con reset. Para borrar. Si, por ejemplo, rebase, yo lo veo desde el punto de vista de reescribir la línea temporal. No borrar la información que tienen sus cómics. Vale, es la funcionalidad real del rebase. Y el cherry pick no borra cómics. Lo que hace es los copia a otras ramas. Por lo tanto, como cherry pick no nos vas a borrar. Tendrías que hacer una mezcla de los comandos en función de su casuística concreta. Bueno, la siguiente pregunta es de, a ver, ¿qué era el localice de Luis Llave? ¿Os ha pasado alguna vez que luego de hacer git-stache os habéis olvidado de ello? Es decir, haber olvidado que se había puesto algo en el stache. A mí no me pasó nunca, pero puede ser algo bastante habitual si lo utilizas de forma continua. Porque en stache es algo, haces unos cuantos cambios y un otra a ramas. Y cuando te das cuenta, eso mejor dentro de cinco, siete días y no tienes ni te acuerdas. Es bastante fácil que te pase. No despistes. Sí, sí, tal cual. Bueno, Adrián Cogo comenta que todo por consola, o necesitas un soporte visual, ¿te ves en cuándo como source tree o yo qué sé? Vale, yo os aconsejo aprender todo por consola y después utilizar en el día a día un editor visual. Yo, por ejemplo, tengo siempre la consola abierta para hacer cosas que el editor visual no me permite. Y aparte, utilizo el source tree para el 80%, 90% del trabajo. Comitear, push, pull, cosas que haces de forma continua, utilizo el source tree, pero siempre sabiendo lo que está haciendo por detrás, es decir, la forma de aprender realmente lo que hace por detrás esa consola. Yo he añadido una preguntita aquí, porque soy muy captadora. Source tree o tower? Yo, en mi caso, utilizo source tree, pero en mi empresa utiliza hay gente que utiliza el tower, hay gente que utiliza otro que está en paralinos, no me acuerdo el nombre. Utiliza varios. Yo, con source tree, últimamente no estoy demasiado contento que tiene bastantes errores. Pero el tower funciona bastante bien, la gente que conozco lo usa hecho para gustos colores. Lo que hay que utilizar uno que sea un poco moderno, porque hay algunos que están bastante desactualizados. Bueno, Alberto, comenta, ¿tú qué usas más? Bitbacket, GitHub o GitLab? Pues mira, en la empresa en la que trabajo utilizamos Bitbacket, porque hasta desde hace mucho tenía una capa gratuita y hasta llegar a un punto en los repositorios privados te permitía hacerlo de forma gratuito. Eso ya lo tienes en GitHub. Ahora mismo, si fuera a arrancar, seguramente nos fuéramos a GitHub. ¿Qué pasa? Que estamos ya en una capa de pago en Bitbacket y moverte es complicado. Cualquiera de ellos te va a dar unos profilades parecidas. Quizá que se ha más avanzado Bitbacket o GitLab. Y con la ventaja que GitLab te permite montártelo. Tigue un servidor propio. Coso que no recomiendo, porque al final tú estás a desarrollar, no a administrar un servidor. Yo te lo digo porque cae en ese error haciéndolo con un servidor propio en Bitbacket y al final nos fuimos a modo de usar. Vale. George Luís Vega pregunta, ¿qué opinión tienes de usar GitFlow y GitLab? Vale. Ambos no te lo puedo decir porque los desconozco. Pero nosotros en mi empresa utilizamos GitFlow con Bitbacket, es decir, utilizarlo con GitLab o como otro, entiendo que será similar. Nuestros llevamos varios años desarrollando GitFlow con la estrategia de ramas de GitFlow y estamos encantados. Somos una empresa pequeña, ¿vale? Ese que hay empresas con bastante más gente da problemas. Somos 8, hay equipos de 3, 4 personas. Perfecto. Vale. David Perez, organizador de la Work and Granada del año pasado, dice, ¿cómo se puede migrar entre Bitbacket y GitLab? Muy buena pregunta. Pues haciendo un clonado, vamos a ver, con algún script. No sé si hay alguna herramienta. Me imagino que habrá herramientas porque hay un día de herramientas para todo. Pero me imagino con algún script que te cloné todas las ramas de todos los reposidores de Bitbacket y eso lo llevase a GitLab. Es decir, con algún script así. Pero ¿qué pasa? Que elementos como ISO o elementos para los que te dan funcionalidades a mayores, tanto Bitbacket como GitLab, posiblemente sea más complicado hacer la migración. Vale. No es demasiado sencillo, ¿eh? Bueno, las migraciones siempre son complejas. Bueno, dice Cristian Marín, digamos que tengo el commit inicial por debajo de 10 commits. Pero olvidé agregar el punto Git Ignore u otra cosa. Se puede hacer como un force a este commit primero o actualizar todo el repo. ¿Qué cosa más complicada? No, vamos a hacer a un commit lo que tendrías que hacer posiblemente sea reescribir tu línea temporal de los 10 commits como acabamos de ver. Es lo más recomendable. Bueno, voy a leer la última pregunta porque quedan dos o tres minutitos para dar un poco de aires y recolocar a la gente. Carlos Longarela dice, excelente charla en la primera. Bueno, Jesús, la verdad es que todo el mundo está muy contento. Para hacer el merge del master con un solo commit limpio, ¿cuál sería la estrategia más adecuada? Rebase, squash, merge, recursive. Yo creo que el squash que acabamos de ver lo que te haces te compacta toda la rama de un único commit y a partir de ahí ya lo llevas mediante un rebase y un fast forward. Es tal cual la pregunta al último ejemplo que acabo de explicar. Vale, vale, perfecto. Pues lo dicho, por dar un poco de oxígeno os cuento que tenéis un enlace a un feedback que es totalmente privado, ¿vale? Que solamente van a ver el feedback de esta charla, el ponente y la organización. Simplemente por interés de mejora que podéis ver en la web de la WorkOn en 2020.spain.workon.org, barra feedback, y ahí hacéis vuestros comentarios y demás. Comento lo que acaba de decir Jesús, que podéis agregarle a preguntas en la sala de Zoom. La sala de Zoom, hay dos salas de Zoom, una para la sala A, otra para la sala B, que habéis recibido en vuestro correo hace dos o tres días. Cuando lo que si estáis incrito, pues os metéis ahí y allí se monta ya la fiesta. Ayer se quedaron hasta las 2 y pico de la madrugada, así que eso ya es un poco excesivo. Pero estuvo así. Allí pilláis Jesús y es un pasillero con los ponentes. Por último, os comento que en este mismo track, vais a tener una charla de estérsela, de crear formularios frontend con unshotted cutoff fields. Y en la otra sala, tendréis 10 formas de implementar tu identidad verbal al contenido de tu web. Os dejamos un minutito para que penséis en qué salgáis Hasta luego y muchísimas latentes. Yo me salgo ahora de estérsela, ¿verdad?