Table of Contents
Git: Sistema de control de versiones
Introducción a los sistemas de control de versiones
Con el objetivo de que durante el curso podáis trabajar con la herramienta git utilizando GitHub como la plataforma para gestionar vuestros repositorios de código, os dejo aqui una serie de instrucciones muy básicas para comenzar a trabajar y realizar al menos las operaciones más esenciales.
Instalación de git
Lo primero que necesitaremos será instalar git en nuestro equipo. Podéis encontrarlo en su página web y, siguiendo las instrucciones del siguiente video, podéis instalarlo sin mayor problema en Windows.
Si utilizáis un Linux Debian o derivados podéis utilizar directamente apt
para su instalación:
santi@zenbook:$ sudo apt-get install git
En el caso de que uséis macOS, lo más sencillo es instalarlo usando brew (https://git-scm.com/downloads/mac):
# Instalar primero brew si no se ha hecho antes santi@zenboo:$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # Instalar git usando brew santi@zenbook:$ brew install git
En cualquier caso no hay que olvidar que debemos configurar git antes de empezar a usarlo. Al menos deberemos configurar nuestra identidad, asignando un nombre y un email al equipo desde el que lo usaremos para identificarnos cada vez que sincronicemos nuestro repositorio local con el remoto (a parte de que además nos pida nuestras credenciales para conectarnos con GitHub)
santi@zenbook:$ git config --global user.name "Santiago Faci" santi@zenbook:$ git config --global user.email "miemail@gmail.com"
También tenemos que tener en cuenta que siempre podremos comprobar esta y otras configuraciones en cualquier momento:
santi@zenbook:$ git config --list user.name=Santiago Faci user.email=miemail@gmail.com . . . . . .
¿Qué es GitHub?
GitHub es una plataforma de alojamiento para sistemas de control de versiones basados en Git. Proporciona alojamiento para repositorios de código fuente accesibles mediante el Sistema de Control de Versiones Git y además amplía el servicio con sus propias funcionalidades, como son Gestión de incidencias, Wiki, Comunidad de usuarios y otros servicios añadidos a lo que es la gestión del código y el proyecto.
Actualmente es la plataforma de alojamiento de código fuente más utilizada (alrededor de 20 millones de usuarios la utilizan) y es especialmente conocida en la comunidad de software libre puesto que un gran número de proyectos de licencias alrededor de este tipo de software se alojan en esta plataforma.
Actualmente GitHub ofrece alojamiento y funcionalidades gratuitas para repositorios públicos (orientados al uso de proyectos de software libre) pero paganado es posible conseguir repositorios privados.
Crear una cuenta en GitHub
El siguiente paso será crear una cuenta en GitHub para acceder a todos los servicios que está plataforma nos ofrece, tanto de gestión de repositorios para nuestros proyectos como de gestión de incidencias, Wiki, . . .
Crear un repositorio en GitHub
Una vez que tenemos una cuenta ya creada, podremos crear repositorios para nuestros proyectos.
En este caso, a modo de ejemplo, crearemos un repositorio remoto en GitHub y más adelante lo actualizaremos con un proyecto que hayamos iniciado en nuestro equipo (repositorio local)
Además, una vez creado el repositorio remoto en GitHub, en nuestro equipo marcaremos nuestro proyecto como un proyecto que será gestionado a través de git y lo configuraremos para que pueda ser gestionado a través de dicha herramienta y fijaremos como repositorio remoto con el que sincronizarse el que acabamos de crear en GitHub.
Marcamos el proyecto como un proyecto que será gestionado con git creando el repositorio local:
santi@zenbook:/miproyecto$ git init
Añadimos la URL del repositorio remoto con el que sincronizaremos nuestros cambios:
santi@zenbook:/miproyecto$ git remote add origin http://github.com/sfaci/miproyecto
Ahora ya tenemos nuestro repositorio local. Podemos continuar trabajando en el proyecto y seguir con el resto de comandos de esta parte cuando tengamos algo listo para subir al repositorio remoto, o bien podemos subir ya lo que tengamos listo en este momento.
Añadimos los cambios que queremos subir al repositorio remoto. En este caso añadimos todo lo que haya en la carpeta del proyecto. Otras veces quizás sólo queramos subir parte de lo que hemos desarrollado (una carpeta o simplemente algunos ficheros sueltos):
santi@zenbook:/miproyecto$ git add .
Marcamos esos cambios como listos para subir y añadimos el comentario para esta validación (commit
)
santi@zenbook:/miproyecto$ git commit -m 'Subiendo los primeros cambios'
Subimos los cambios al repositorio remoto a la rama main
(por ahora sólo trabajamos en esa rama directamente)
santi@zenbook:/miproyecto$ git push origin main
Subir un cambio en el proyecto al repositorio remoto
A medida que avancemos en el desarrollo de nuestra aplicación nos puede interesar ir subiendo algunos cambios al repositorio remoto. Lo podemos hacer en cualquier momento y además hay que tener en cuenta que no es necesario subir todo aquello que hayamos cambiado, sino que podemos añadir (git add
) sólo aquellos cambios que nos interese.
santi@zenbook:/miproyecto$ git add ficheros-o-carpetas
Marcamos esos cambios como listos para subir y añadimos el comentario para esta validación (commit
)
santi@zenbook:/miproyecto$ git commit -m 'Comentarios sobre los cambios'
Subimos los cambios al repositorio remoto a la rama en la que estemos trabajando
santi@zenbook:/miproyecto$ git push
El fichero README
Es un fichero, que podemos escribir en síntaxis Markdown, donde podemos realizar una breve descripción de nuestro proyecto y que GitHub se encargará de renderizar en la portada de la web de nuestro repositorio. Así, es bastante habitual incluir las siguientes secciones:
- Título del proyecto
- Descripción del proyecto
- Requisitos para la instalación
- Guía rápida de instalación (y si hay más documentación se enlaza aqui, por ejemplo a la Wiki del proyecto)
- Enlace a la web (si la hay)
- Información sobre los autores del proyecto
Hay que tener en cuenta la importancia de este fichero ya que es la primera descripción que un usuario encontrará cuando acceda a nuestro repositorio
El gestor de incidencias
El gestor de incidencias (issues) de GitHub permite registrar cualquier tipo de incidencia (bug, enhancement, proposa o task) en la plataforma para que pueda ser gestionada y tratada por el equipo de desarrollo. Las incidencias deberán ser asignadas a un usuario que será el encargado de resolverla. Conviene tener en cuenta que hay que marcarlo en el momento de crear el repositorio si queremos poder utilizarlo.
Lo más importante a la hora de registrar una incidencia es asignarle un título y descripción para que sea fácil de encontrar y reproducir por quién tenga que resolverla (incluso aunque sea uno mismo, no siempre se pueden resolver las incidencias en el momento de encontrarlas y más tarde quizás olvidemos algún detalle). Menos importante pero interesante será definir la inmportancia de la issue (ayudará a priorizar) y el tipo de incidencia:
- bug: Un fallo que se ha localizado en el código
- enhancement: Una mejora sobre el código ya escrito
- proposal: Una propuesta sobre el código que ya funciona
- task: Una tarea que debe realizarse. No tiene porque ir asociada a ningún problema o bug de código
También podemos adjuntar algún fichero, como por ejemplo capturas que ayuden a detectar o comprender mejor el problema.
Por último, la incidencia puede ser directamente asignada a un usuario (incluso a uno mismo). En caso de que no se sepa quién debe realizarla se puede dejar en blanco esperando que el responsable decida quién la tiene que corregir.
La vista de incidencias tiene filtros automáticos que permiten localizar las incidencias rapidamente por su estado.
Además, el gestor de incidencias de GitHub permite realizar ciertas gestiones sobre las mismas utilizando una serie de comandos que directamente pueden ser aplicados cuando se realizan los commit sobre el código con el comando git. Una lista de los comandos y opciones disponibles se puede encontrar aqui.
Por ejemplo, si tenemos una incidencia abierta con el número #13 que hace referencia a un bug en cierta parte del código, cuando resolvamos el error y nos dispongamos a hacer el commit que soluciona dicho problema, podemos ejecutar ese comando de la siguiente forma:
santi@zenbook:$ git commit -m 'Corregido el fallo que impedía conectar con la Base de Datos fix #13'
De esta forma, la incidencia con el número #13 será automáticamente marcada como resuelta sin que tengamos que acceder con el navegador al gestor de incidencias y resolverla manualmente a través de la web. Además, el mensaje del commit quedará asociado como mensaje de resolución de dicha incidencia.
La Wiki
Siempe que creemos por primera vez un repositorio en GitHub tendremos la oportunidad de decidir si queremos que se integre una Wiki con él.
A través de la Wiki podremos crear documentación asociada a nuestro proyecto/repositorio utilizando como síntaxis Markdown para su edición. En la página de GitHub puedes encontrar una Guía para la Wiki de GitHub que puedes usar con la plataforma para saber cómo trabajar con la Wiki y para conocer la sintaxis que debes usar para editarla.
Descargar un repositorio y actualizarlo
Por otra parte, también podemos necesitar acceder a un repositorio remoto ya creado para continuar a partir de ese trabajo ya realizado e ir subiendo nuevos cambios a medida que los realizemos. Para eso podemos clonar un repositorio remoto en nuestro equipo, realizar los cambios que vayamos necesitando y subir dichos cambios (a medida que nos interese) al repositorio remoto de donde clonamos inicialmente el proyecto.
santi@zenbook:$ git clone https://github.com/usuario/miproyecto
Ahora podemos trabajar en el proyecto y, cuando queramos subir los cambios realizados, podemos proceder como antes hemos visto y actualizar el repositorio remoto:
santi@zenbook:/miproyecto$ git add ficheros-o-carpetas santi@zenbook:/miproyecto$ git commit . . . . . . . . .
Arreglar conflictos
Cuando dos programadores trabajan sobre el mismo fichero de código, se puede llegar a producir un conflicto.
Supongamos un fichero sobre el que un programador ha hecho algún cambio que ha subido al repositorio remoto. Cuando un segundo programador intente subir un cambio sobre ese mismo fichero, se producirá un conflicto en el momento en que éste intente poner al día su repositorio (pull
) antes de subir sus cambios.
El segundo programador tendrá que arreglar el conflicto antes de poder subir definitivamente su cambio (tras la decisión que haya tomado acerca de cómo fusionar su parte con la de su compañero).
Revisión de código y Pull Requests
Gitflow
Gitflow es un flujo de trabajo con Git muy extendido. La idea es crear dos ramas principales y de duración infinita (main y develop) y una serie de ramas de apoyo que surgen de éstas (para implementar nuevas funcionalidades o liberar nueva versiones, por ejemplo).
- La rama main (o master) se considera la rama principal del proyecto y contendrá el código estable
- La rama develop es la rama de trabajo o desarrollo. Es en la que se acaban fusionando todas las ramas de apoyo para hacer avanzar el proyecto. Sobre ésta se harán las pruebas necesarias antes de que una nueva versión del proyecto pueda llevarse a la rama main para generar una nueva versión
Asi, a medida que se necesiten desarrollar nuevas funcionalidades (features), éstas se harán en nuevas ramas creadas expresamente para dicha funcionalidad. Se trabajará en ella y, cuando esté terminada, se fusionará con develop para incorporar el código a la rama de desarrollo.
Cuando llega el momento de liberar una nueva versión, se crea una nueva rama con el objetivo de comenzar el ciclo de liberación. Ya no es posible incorporar nuevas funcionalidades a esta nueva rama (nueva release) sino que solamente se corrigen fallos y cualquier otra tarea relacionada con la liberación de la nueva versión. Finalmente, cuando está lista, se fusiona con la rama principal (main).
Si nos fijamos en el flujo de trabajo, veremos que es posible que, mientras una parte del equipo trabaja en liberar y preparar la nueva versión, otra parte del mismo puede seguir trabajando, al mismo tiempo, en las nuevas funcionalidades de la siguiente versión.
Comandos git
Comprobar el estado de repositorio
santi@zenbook:/miproyecto$ git status On branch develop Your branch is up to date with 'origin/develop'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: README.md modified: masc/print_utils.py modified: setup.py Untracked files: (use "git add <file>..." to include in what will be committed) samples/ no changes added to commit (use "git add" and/or "git commit -a") santi@zenbook:/miproyecto$ |
Ver las ramas existentes
Todas las ramas
santi@zenbook:$ git branch -a
Las ramas locales
santi@zenbook:$ git branch
Las ramas remotas
santi@zenbook:$ git branch -r
Crear una nueva rama
santi@zenbook:$ git checkout -b develop
Cambiar de rama
santi@zenbook:$ git checkout develop
Fusionar ramas
En este caso suponemos que queremos fusionar la rama develop en la de main
santi@zenbook:$ git checkout main santi@zenbook:$ git merge develop
Fusionar ramas via Pull Request
Eliminar un fichero del repositorio remoto
Hay que tener en cuenta que en este caso eliminaremos el fichero tanto del repositorio remoto como del local
santi@zenbook:$ git rm Fichero.java
Y en el caso de un directorio
santi@zenbook:$ git rm -r directorio
Evitar que algunos ficheros/carpetas formen parte del repositorio
También es posible evitar que algunos ficheros o carpetas o incluso extensiones determinadas pasen a formar parte del repositorio de forma permanente. En este caso hablamos de que estos ficheros se ignoran incluso aunque estén dentro de alguna carpeta que se incluya para ser gestionada como parte del repositorio. De esa manera podemos trabajar más cómodamente sin necesidad de ir teniendo cuidado de no incluirlos.
En este caso pensamos en ficheros como los .class
generados al compilar una clase Java, o los .jar
, las carpetas que almacenan las configuraciones de los proyectos en cualquier lenguaje y también cualquier otro fichero que quizás queramos usar para el desarrollo pero no sea necesario enviar al repositorio como parte del código del proyecto.
En este caso es necesario crear un fichero con el nombre .gitignore
en la carpeta raíz del repositorio y añadimos los ficheros, carpetas o extensiones que queremos que se ignoren. A continuación se muestra un ejemplo.
- .gitignore
# Ficheros generados Java *.class *.jar # Ficheros OSX .DS_Store # Carpetas que contienen ficheros generados bin/ out/
Por último, y una vez creado el fichero, se tendrá que añadir como parte del repositorio como cualquier otro. Se permite que se hagan cambios siempre y cuando se validen y suban como corresponde.
Dejar de mantener un fichero en el repositorio remoto
Ahora suponemos que queremos dejar de sincronizar con el repositorio remoto un fichero pero queremos seguir manteniéndolo en el repositorio local porque, por ejemplo, queremos que forme parte del proyecto pero sólo en nuestro equipo.
santi@zenbook:$ git rm --cached Fichero.java
Y para el caso de un directorio
santi@zenbook:$ git rm -r --cached directorio
Y si además lo que realmente queremos es que esos ficheros o carpetas no formen parte del repositorio remoto podemos hacer que sean ignorados añadiéndolos el fichero .gitignore
Eliminar del repositorio remoto ficheros eliminados ya en local directamente
Al utilizar Git deberíamos utilizar el comando git rm
para eliminar cualquier fichero del repositorio. Si por alguna razón ya hemos eliminado algunos ficheros del proyecto directamente sin utilizar el comando anterior, Git nos pedirá todavía que hagamos los cambios efectivos para el repositorio remoto si queremos hacer el correspondiente commit
para que estos ficheros se eliminen en nuestro repositorio en Internet.
En ese caso, podemos utilizar este comando, que marca como eliminados para el repositorio remoto todos aquellos ficheros que hayamos eliminado en local directamente.
santi@zenbook:$ git rm $(git ls-files --deleted)
Obtener el historial de commits del repositorio
Podemos obtener el historial de cambios (commits
) utilizando el comando git log
(para salir del historial hay que pulsar la tecla escape)
santi@zenbook:$ git log commit f1f20725ad152654bf7684b324109b1eace75b04 Author: . . . Date: Sat Nov 4 10:44:37 2017 +0100 Cambios para hacer que funcione algo commit e63e2b06f7fe4b724dabe78d437baa964ad384f6 Author: . . . Date: Sat Nov 4 10:43:12 2017 +0100 Ya se puede registrar commit a1160bce457b6e86f1cd7bb40205703f269dcb57 Author: . . . Date: Sat Nov 4 02:59:08 2017 +0100 Arreglado el bug de eliminar . . . . . .
También podemos visualizar una versión reducida de este historial utilizando la opción –oneline
:
santi@zenbook:$ git log --oneline f1f2072 Cambios para hacer que funcione algo e63e2b0 Ya se puede registrar a1160bc Arreglado el bug de eliminar . . . . . .
Obtener el estado del código para un commit determinado
Si conocemos el hash de un commit concreto, podemos obtener el estado del código en el momento de dicho commit utilizando el comando git checkout
pasando el hash de dicho commit como se muestra en el ejemplo.
santi@zenbook:$ git checkout a1160bce457b6e86f1cd7bb40205703f269dcb57 Note: checking out 'a1160bce457b6e86f1cd7bb40205703f269dcb57'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b new_branch_name HEAD is now at a1160bce... Arreglado el bug de eliminar
Para conocer el hash del commit podemos utilizar el comando git log
tal y como se explica en el punto anterior o bien acceder a la sección de GitHub o Bitbucket donde se muestra dicho historial desde la misma web.
Y para volver al estado actual, en este caso a la rama master, que es donde estaba trabajando:
santi@zenbook:$ git checkout master Previous HEAD position was a1160bce... Arreglado el bug de eliminar Switched to branch 'master' Your branch is up-to-date with 'origin/master'.
© 2020-2024 Santiago Faci