En esta guía para principiantes vamos a ver los comandos necesarios para poder solventar las casuísticas más comunes que nos encontraremos con Git y GitHub en el día a día de un entorno profesional: crear un repositorio, guardar los cambios, información en los commits y el historial y subir los cambios a GitHub.
Para esta primera parte utilizaremos como ejemplo una ETL en Python, que iremos desarrollando y versionando con Git. Haremos un pequeño procesado de datos, que subiremos a GitHub y simularemos algunos ejemplos de casos prácticos en los que desarrollaremos nuevas funcionalidades en la ETL, corregiremos bugs y trabajaremos con pull-request colaborativas.
Para este taller y sucesivos es necesario utilizar la terminal de macOS/Linux o Git Bash de Windows y opcionalmente tener Python con Anaconda instalado. Revisa el artículo de instalación y el de configuración si todavía no lo has hecho.
Git – Estadodel entorno
Cómo saber si Git está correctamente instalado
Simplemente con introducir git
en la línea de comandos ya sería suficiente. Si nos sugiere sus comandos, es que está correctamente instalado, de lo contrario, tendremos que instalarlo. Mírate nuestra guía de Instalación y herramientas imprescindibles para utilizar Git y GitHub.
Comprobamos que está correctamente instalado, y de paso chequeamos la versión.
git --version
Configuración de Git y GitHub
Una buena manera de saber en qué estado está la configuración de Git es mediante el archivo ~/.gitconfig
. Se trata del archivo de configuración del usuario sistema, que podremos modificar o bien desde el archivo o mediante comandos.
git config --global -e
Para saber si GitHub va a reconocer tu máquina, asegúrate de haber configurado o bien la conexión por SSH o el PAT. La manera de configurarlos la tienes en nuestra Guía completa para configurar Git y GitHub.
Recuerda que por un lado tendremos el repo local y por otro lado el server remoto, el de GitHub.
Git – Creación de repo, estado y primer commit
Creación de repo desde local – git init
Una vez tenemos ya todo bien instalado y configurado. Vamos a crear un repositorio, a ver cómo estructura Git la información, y a conocer los archivos de configuración que se generan.
Crea una carpeta sin espacios, en minúscula y sin caracteres raros. Es especialmente importante el tema de los espacios y los caracteres raros, ya que usaremos esta carpeta como nombre de repo en GitHub.
Escogeremos como nombre de repo presentation_etl, simulando un repositorio donde irán todas las ETLs de la capa de presentación de datos para el departamento de analistas.
mkdir presentation_etl
cd presentation_etl
git init
TIP: no pongas un nombre muy específico, ya que si el código escala y abarca otras funcionalidades, el nombre no será representativo.
Fíjate que dentro de presentation_etl se ha creado una carpeta llamada .git
, donde Git guarda todos los metadatos asociados a este repositorio. Con ls
no verás la carpeta ya que está oculta y tendrás que usar ls -a
. Habilita igualmente los archivos ocultos en el explorador de archivos.
Vemos también que aparece main entre paréntesis. Es la branch por defecto (veremos más adelante) sobre la que estamos trabajando.
¿Qué hay dentro de la carpeta .git?
Dentro de la carpeta .git se encuentran los archivos y subdirectorios que conforman el repositorio de Git. Estos archivos y directorios son esenciales para el funcionamiento y la gestión del repositorio. Esto es lo que te vas a encontrar en la carpeta .git:
- HEAD: Es un archivo que indica la referencia a la rama o commit actual en la que te encuentras trabajando. Veremos más en detalle después
- config: Este archivo almacena la configuración específica del repositorio, como los alias de los comandos de Git y los ajustes de comportamiento.
- objects: Es un directorio que contiene los objetos del repositorio, como commits, árboles y blobs. Estos objetos son los componentes fundamentales que conforman la estructura de un repositorio de Git.
- refs: Directorio que almacena las referencias, como las ramas (branches) y las etiquetas (tags), que apuntan a los diferentes commits en el historial del repositorio.
- hooks: Aquí podemos colocar scripts personalizados que se ejecutarán en respuesta a ciertos eventos de Git, como antes o después de un commit, push o merge.
- index: Es un archivo que actúa como una “zona de preparación” (Staging Area) y almacena la información sobre los archivos que están listos para ser confirmados en el próximo commit.
Working Directory vs Staging Area vs Repository
Recordemos cómo gestiona Git los cambios en el proyecto.
El Working Directory (Directorio de trabajo) es el directorio en tu ordenador donde trabajas con los archivos de tu proyecto. Contiene todos los archivos, incluidos los que aún no se han rastreado o agregado a Git.
El Staging Area (Área de preparación) es una etapa intermedia entre el Working Directory y el Repository. Es donde seleccionas y preparas los archivos que se incluirán en el próximo commit. Los archivos en el Staging Area están listos para ser confirmados en el historial del repositorio, pero aún no se han registrado definitivamente en el Repository.
El Repository (Repositorio) es la base de datos de Git que almacena el historial completo de commits y otros objetos relacionados. El Repository contiene todos los commits realizados, junto con sus metadatos, como autor, fecha y mensaje. También incluye información sobre las ramas, etiquetas y referencias del proyecto.
Por tanto, todo lo que trabajemos en nuestro ordenador estará en el Working Directory. Añadiremos al Staging Area todo lo que queramos en el próximo commit, y en el repositorio se encontrarán los commits, con los cambios ya versionados.
Cambios en archivos. ¿Cómo se que hay cambios en local? – git status, git add
Veamos qué ocurre cuando creo o modifico algún archivo. Primero, creamos una aplicación (script) en Python. Lo puedes hacer desde la línea de comandos, o directamente en la carpeta del repositorio. Creas un script sales.py, y añades el siguiente código.
import pandas as pd
# Data load
products = pd.DataFrame({'Name': ['Shirts', 'Shorts', 'Trousers'], 'Price': [50, 35, 60]})
¿Cómo sería mediante línea de comandos?
$ touch sales.py
$ nano sales.py
Puedes usar el editor de tu preferencia, vim, nano… modificamos y listo
Y tendríamos el archivo creado:
Ahora bien, ¿Qué ha pasado en Git? Con git status
podemos ver el estado del repositorio.
git status
¿Qué información proporciona git status
?
- Branch en la que estamos: main.
- Archivos del Workign Directory que todavía no están en el Staging Area: el archivo sales.py.
- Archivos añadidos al Staging Area pero que todavía no se han comiteado (no están en el Repository): ninguno, porque no hay nada en el Staging Area.
Prueba a añadir sales.py al Staging Area. Para ello hay que usar el comando git add <file1> <file2>
. Ahora con git status
nos indicará que hay cambios que necesitan ser commiteados.
git add sales.py
git status
¿Y si queremos añadir todos los cambios? Y no archivo a archivo
Git ya está preparado para esa tarea, ya que es de lo más habitual. Simplemente añádele un punto al comando git add, en vez de especificar todos los archivos modificados.
git add .
Deshacer cambios que he añadido al Staging Area
Si nos hemos equivocado y queremos quitar cambios que habíamos metido en el Staging Area, lo podemos hacer mediante el comando git reset
git reset sales.py
git reset
Hasta la versión 2.23 se utilizaba git restore, por lo que asegúrate de tener git actualizado para usar git reset.
Si quieres ver qué cambios hay en el Staging Area, pendientes de ser commiteados:
git diff --staged
Guardar los cambios en el repositorio – git commit -m “commit message”
Una vez incorporamos los cambios al Staging Area, los guardaremos en el propio repositorio, y para ello crearemos un commit, una nueva foto, una nueva versión del programa.
git commit -m "Product information loaded"
El único argumento que hemos añadido es el -m
, que significa que tenemos que añadir un mensaje.
Argumentos interesantes del comando git commit
El comando git commit en Git ofrece varios argumentos que resultan útiles para personalizar y mejorar el proceso de confirmación de cambios. Algunos de los argumentos más destacados son:
- -m “mensaje”: Permite especificar un mensaje descriptivo para el commit directamente en la línea de comandos. Es útil para agregar una breve descripción de los cambios realizados en el commit.
- -a: Hace que Git agregue automáticamente los archivos modificados y eliminados al commit. No es necesario usar el comando git add antes de hacer el commit. Sin embargo, este argumento no incluye archivos nuevos que no hayan sido rastreados previamente.
- –amend: Permite modificar el commit más reciente. Al usar este argumento, puedes agregar cambios adicionales al commit anterior o incluso modificar el mensaje de commit.
- –author=”nombre
: Permite especificar el nombre del autor y la dirección de correo electrónico para el commit. Esto puede ser útil en casos en los que deseas cambiar o establecer manualmente el autor del commit. - -p o –patch: Hace que Git muestre las diferencias línea por línea y te permite elegir qué cambios incluir en el commit. Puedes interactuar con cada diferencia y decidir si deseas agregarla o no al commit.
Buenas prácticas de git commit
Lo más probable es que trabajes en equipo con otros desarrolladores, y por tanto tengáis que seguir unas pautas para facilitar el trabajo con Git y hacer más entendibles sus logs.
Sigue una estructura en los commits. Especifica el tipo del commit, titulo, y opcionalmente cuerpo del commit. En el tipo podría ser una nueva funcionalidad, el arreglo de un bug, de estilo, testing, refactorización, documentación o mantenimiento.
En el título del commit se breve y conciso. Los commits no pueden ser multipropósito, así que pon dos commits en caso de que hayas arreglado dos bugs diferentes. De forma opcional puedes añadir un cuerpo para más detalle del commit, donde puedes poner el contexto del commit para que lo entienda el lector.
Testea el código siempre que vayas a añadir un commit nuevo, para que lo que haya en el repositorio sea correcto.
Realiza commit cada poco tiempo, no esperes a acumular un código monstruoso.
Información del historial de commits – git log
Una vez tenemos ya cargado nuestro primer commit, podemos revisar el historial de commits mediante git log
:
git log
¿Qué tenemos en el git log?
- Lista de commits. De momento un único commit
- Id de commit/Hash: identificador único de cada commit
- HEAD: lo veremos más adelante, pero básicamente es dónde está apuntando el repositorio.
- Autor y correo del commit
- Datetime del commit
- Mensaje del commit
Después hemos ejecutado un git status
para comprobar que no hay más cambios pendientes ni en el Working Directory ni en el Staging Area.
¿Cómo tener un log de git más amigable?
Tienes varias opciones, nosotros te proponemos estas tres:
- Software compatible con Git: Ésta es sin duda la más cómoda. GitHub Desktop, VS Code, Pycharm tienen visualizaciones mucho más entendibles que el git log básico.
- Resumen en una línea: Compacta el log para que ocupe cada commit una línea: git log –graph –oneline –all
- Formato del commit: También es posible modificar el formato del commit a nuestro gusto: git log –graph –abbrev-commit –decorate –date=relative –format=format:’%C(bold blue)%h%C(reset) – %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)’ –all
Información de un commit – git show <commit-hash>
Podemos consultar también qué cambios se efectuaron en un commit concreto mediante git show <commit-hash>.
Aparte de la información que ya veíamos en git log
, tendremos los archivos modificados y las líneas a las que afectó.
git show 9879ab4f68bf
Git/GitHub – Interacción con repo remoto
Conexión a repositorio remoto y subida de cambios – git remote y git push
Hasta ahora hemos trabajado con Git de forma individual, pero no será lo habitual, sino que tendremos que colaborar en proyectos de código con varios compañeros. Esto es posible gracias a plataformas de gestión de repositorios de Git como GitHub.
Si queremos trabajar con un repositorio en GitHub, tenemos tres opciones:
- Comenzar en un proyecto Git en local y subirlo a GitHub posteriormente.
- Iniciar un proyecto de cero en GitHub, clonarlo en local y empezar a trabajar.
- Forkear un repo de terceros, clonarlo en local y empezar a trabajar desde esa versión.
¿Qué es fork en Git?
Un “fork” en Git es una copia independiente de un repositorio existente. Cuando haces un fork de un repositorio, creas una versión propia de ese repositorio en tu cuenta de GitHub (o en otro servidor Git). El fork te permite realizar cambios en el repositorio sin afectar el repositorio original. Puedes hacer modificaciones, agregar nuevas características y enviar solicitudes de extracción para proponer tus cambios al repositorio original. El fork es una forma común de contribuir y colaborar en proyectos de código abierto
Hasta ahora hemos creado un proyecto, llevamos hecho un trabajo, y lo queremos subir a GitHub. Dado que llevamos muy poco de proyecto, la segunda opción también sería válida: crear un repo nuevo, clonarlo y copiar ahí los archivos para posteriormente subirlos. Ahora bien, no sería lo recomendable porque ya tenemos un repo en local un un historial de commits que perderíamos.
En nuestro caso, vamos a crear un repo en GitHub, que linkaremos a nuestro repo en local para posteriormente subir los cambios.
Creamos un repo en GitHub:
- Ponle el nombre del repo en local: presentation_etl
- ¿Público o privado? Por sencillez lo puedes poner público, aunque si lo pones privado puede ser una buena manera para comprobar que configuraste correctamente SSH o PAT.
- No añadas un README: todo repositorio tiene que llevar un descriptivo inicial, aunque por sencillez del ejemplo lo dejaremos sin README.
- .gitignore: aquí configuramos qué archivos queremos que ignore Git, y que por tanto ni se guarden en el repo ni se suban a GitHub. De momento esto lo dejamos como está.
- License: De momento lo mismo que .gitignore.
Bien, ahora vamos a decirle al repo local dónde está el repo remoto para que pueda subir los cambios.
Fíjate que vamos a subir un repo con una rama main y con un nombre (presentation_etl), a otro repo en GitHub exactamente igual, por lo que es fundamental que el repo de GitHub esté totalmente vacío para evitar conflictos.
git remote add origin git@github.com:nombre_usuario_github/presentation_etl.git
git push -u origin main
El argumento -u
de git push
es la abreviación de set-upstream
.
Fíjate que llevamos a cabo algunas comprobaciones para ver que efectivamente está bien configurada la URL del repositorio remoto:
git config --get remote.origin.url
git remote show origin
¿Qué es origin?
En Git, “origin” es el nombre por defecto utilizado para referirse al repositorio remoto desde el cual se clonó o con el cual se está trabajando. Cuando clonas un repositorio remoto, Git automáticamente configura “origin” como un apodo para ese repositorio remoto.
El nombre “origin” es convencional y no tiene ningún significado especial en sí mismo. Puedes cambiar el nombre “origin” a otro nombre que elijas si así lo deseas, aunque es comúnmente utilizado y se recomienda mantenerlo como “origin” por convención.
Si acudimos al repo en GitHub ya no está vacío, y encontraremos allí nuestro primer commit.
TIP: Si hemos creado algun archivo en GitHub antes de aplicar el upstream, van a aparecer conflictos, ya que estamos en la misma rama e intentamos subir una nueva rama que se llama igual. Podemos sobreescribirlo todo con el argumento -f
(force) en git push -u -f origin main
. Esto hará que prevalezcan los cambios de local.
Actualizar repo local con cambios del remoto – git pull, git fetch
Ya tenemos los primeros pasos del proyecto subido, ahora simularemos que estamos en un proyecto colaborativo y que un compañero añade un README al repo de GitHub. Esto lo vas a poder hacer directamente desde la interfaz de GitHub, pero se recomienda que se trabaje siempre desde local y se suba después.
Veamos como sería el diagrama de ramas:
Ya tendríamos dos commits en el repo remoto. Procedemos a actualizar el repo local:
git pull origin main
TIP: Poniendo solo el comando git pull
sería suficiente. Git ya da por hecho que quieres actualizar en local los cambios de la rama a la que está apuntando por defecto en remoto: origin.
¿Y si simplemente queremos ver qué nuevas actualizaciones hay en remoto?
Hemos hecho algo de trampas porque directamente hemos juntado lo que hay en remoto con lo que hay en local, pero ¿y si de momento quiero ver las novedades del repo remoto sin que me modifique los cambios de mi rama local? Y ya después si son correcto los incorporamos al repo local. Para ello utilizaremos git fetch
:
git fetch
Entonces ¿qué diferencia hay entre git pull y git fetch?
La diferencia principal entre git pull
y git fetch
radica en que git pull
obtiene los cambios remotos y realiza automáticamente una fusión, mientras que git fetch
solo obtiene los cambios remotos y te permite decidir cómo fusionarlos posteriormente. Si quieres tener un mayor control y revisar los cambios antes de fusionarlos, puedes optar por git fetch
. Si deseas obtener los cambios remotos y fusionarlos de inmediato, puedes utilizar git pull
.
git pull = git fetch + git merge
Clonar un repositorio – git clone
En apartados anteriores hemos partido de un repo local con código. Pero ¿y si queremos empezar un proyecto de 0? O queremos bajarnos un repo para seguir trabajando en el mismo. Para ello llevaremos a cabo una operación llamada git clone
, que es distinto de descargar, puesto que en la descarga simplemente nos bajamos archivos, mientras que en el clone bajamos toda la traza de Git del proyecto.
Primero accedemos a la URL del repositorio:
Copiamos la URL y la añadimos al git clone
en la terminal. Recuerda que esto va a crear un repo nuevo, por lo que procura estar fuera de la carpeta de otro repo.
git clone https://github.com/daorti/presentation_etl.git
¿Clone con HTTP o SSH? Lo normal es por HTTP, ya que no siempre tendremos configuradas las claves SSH, aunque en nuestro caso no habría problema porque ya lo teníamos configurado.
Fíjate que si haces un git log
, no solo tiene los mismos archivos que el repo remoto de GitHub, sino que también el mismo historial de commits.
Bonus track – .gitignore
Cuando creamos el repositorio desde GitHub, nos sugirió introducir un archivo llamado .gitignore. Pero ¿qué es esto del .gitignore?
Se trata de un archivo especial en Git que permite especificar qué archivos y directorios deben ser ignorados y excluidos del control de versiones. Cuando se agrega un archivo o patrón al .gitignore
, Git no rastrea ni incluye esos archivos en los commits ni en las operaciones de Git, lo que ayuda a evitar la inclusión accidental de archivos sensibles, generados automáticamente o innecesarios en el repositorio. El .gitignore
es útil para mantener limpio y organizado el repositorio al filtrar los archivos que no deben ser versionados.
¿Cómo se crea uno de estos?
- Montamos un archivo vacío llamado “.gitignore”. Es importante que se llame así, tal cual, sin extensiones de .txt ni nada. En tu explorador de archivos se tienen que ver las extensiones de los archivos.
- Lo colocamos en la raíz del proyecto
- Añadimos todas las extensiones de archivos que no queramos incorporar al repositorio. Por ejemplo, si queremos que ignore los archivos csv, simplemente ponemos *.csv en una línea nueva. O si queremos que ignore una carpeta, añadimos nombre_carpeta/
Algunas recomendaciones
- Úsalo para evitar subir metadatos del sistema operativo o de IDEs. Jupyter, VSCode o Pycharm crean carpetas con metadatos que no queremos subir al repositorio. Incluso macOS también genera archivos que sobran en el repo (.
DS_Store
). Podemos hacer que Git ignore estas carpetas. - Evita archivos pesados. Si vas a trabajar con CSVs pesados, archivos masivos parquet, o el archivo que sea de gran tamaño, siempre puedes añadir sus extensiones para que no se suban.
- Úsalo para no subir carpetas concretas o archivos con un formato concreto.
- Tampoco subas environments de Python, ni repositorios con paquetes.
Ejemplo de .gitignore
# Generated by MacOS
.DS_Store
# Visual Studio Code
.vscode/
# Jupyter Notebook
.ipynb_checkpoints
# Pycharm
.idea
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
Ten en cuenta que Git va a empezar a ignorar los archivos desde que pongas el .gitignore
en el repositorio, es decir, todo lo que hayas guardado en commits anteriores ya forma parte del histórico de versiones del repositorio, y por tanto esos archivos no serán eliminados de los commits.
A modo de prueba, crea tu .gitignore, añade *.txt (que ignore los archivos de extensión txt), y commitea los cambios. A continuación crea un archivo txt nuevo, ve a git status
y comprueba que Git no detecte ningún cambio en el Working Area.
Resumen
En este artículo has aprendido a crear repositorios tanto en local como en remoto, consultar el estado de los cambios del repositorio, manejar y añadir cambios con nuevos commits, realizar publicaciones en el repositorio remoto y crear un archivo de configuración para ignorar los archivos que no nos interesan.
SIGUIENTE EPISODIO – Te recomendamos que continúes tu travesía por Git y GitHub con nuestro artículo para dominar las ramas con Git, realizar merges, pull-request y resolver conflictos en el merge.
Resumen de comandos utilizados
Comando | Descripción |
---|---|
Estado y versión de Git | git –version |
Ver configuración | git config –global -e |
Inicializar un repo | git init |
Ver estado de cambios | git status |
Añadir cambios al Staging Area | git add |
Deshacer cambios | git reset |
Guardar cambios en el repo | git commit -m “message” |
Historial de commits | git log |
Ver qué hay en un commit | git show <commit-hash> |
Añadir URL a repo local | git remote add |
Subir cambios a repo remoto | git push |
Subir una rama nueva a repo remoto | git push -u |
Bajar y mergear cambios | git pull |
Bajar cambios | git fetch |
Clonar un repositorio | git clone |
Pingback: We Learn Data
Pingback: We Learn Data