Git & GitHub Avanzado

Sumario

  1. Fundamentos del branching 
  2. Flujos de trabajos profesionales
  3. Fusionar ramas
  4. Estrategias avanzadas
  5. Gestión de conflictos
  6. GitHub 2.0
  7. Demo
  8. Bonus

Fundamentos del branching

Imagina esta situación...

Piensa en versiones que heredan de un mismo proyecto...

Una por cada colaborador

... o una por propósito

... como un árbol con un tronco y sus ramas

El árbol de Git

  • Desarrollo en paralelo.
  • Experimentación segura de nuevas ideas.
  • Control de calidad.
  • Gestión de múltiples versiones en simultaneo.
  • Organización por funcionalidades.

Beneficios de trabajar con branches (ramas)

Creación de ramas: 2 maneras

1. Crear la rama y luego moverse a ella (usando dos comandos):

git branch <nombre_rama>
git checkout <nombre_rama>

Ejemplo:

2. Crear y moverse a la rama con un solo comando:

git checkout -b <nombre_rama>

Ejemplo:

Otros comandos básicos y útiles

a. Obtener una lista con los nombres de las ramas existentes:

git branch --list

Ejemplo:

b. Eliminar ramas:

git branch --delete <nombre_rama>

Ejemplo:

Flujos de trabajo profesionales

Podemos crear muchas ramas... ¿verdad?

Sí, pero... ¡sería un gran pandemonio! 😱

Trunk-based development

Un flujo de trabajo para cada estilo de desarrollo

Git-flow

Trunk-based development

  • Todos los desarrolladores trabajan sobre una sola rama y tienen completo acceso a ella. Pueden crear ramas de corta vida que luego fusionan con la principal.

  • Agiliza el desarrollo.

  • Evita que los desarrolladores creen conflictos de fusión (merge conflicts) difíciles de resolver.
  • Se está comenzando.

  • Se requiere iterar rápidamente.

  • Trabajas con un gran número de desarrolladores senior.

Ideal cuando:

Git-flow

  • Una rama principal: master o main.
    Varias ramas adicionales: develop, release, hotfix, feature, etc.

  • Estricto control.
  • Requiere creación de pull requests.
  • Gestionas proyectos open-source.

  • Cuentas con varios desarrolladores juniors.

  • Dispones de un producto establecido.

Ideal cuando:

Convención de nombrado de branches

Estructura básica del comando:

tipo/descripcion-breve-ID

Buenas prácticas

Usar guiones para separar palabras.

✅ Todo en minúsculas.

Ser descriptivo pero conciso.

Si se trata de un ticket, incluir ID.

Conviene evitar:

 camelCase o PascalCase.

 Espacios en blanco.

 Nombres muy largos.

 Caracteres especiales y acentos.

Se recomienda:

Ejemplos:

feature/mercadopago-integration
bugfix/login-validation-#445
hotfix/security-patch-v2
release/v2.1.0
docs/api-documentation

Algunos tipos comunes:

  • feature/ : nuevas características
  • bugfix/  : correcciones no urgentes
  • hotfix/  : correcciones urgentes
  • release/ : preparación de versiones
  • docs/        : documentación
  • test/    : pruebas
feature/
bugfix/
hotfix/
release/
docs/
test/

Fusionar ramas

¡Fusión!

Merge vs Rebase

git rebase

git merge

Git merge

  • Combina los cambios de ambas ramas.

  • Mantiene el historial de ramificaciones visible.
  • Es seguro y no destructivo.
  • Ideal para ramas públicas.
  • Trabajas en equipo.

  • Hay ramas compartidas.

  • La trazabilidad es importante.

Es ideal usarlo cuando:

Fusión con git merge

Estructura básica del comando:

git checkout <rama-destino>
git merge <rama-origen>

Ejemplo:

Git rebase

  • Mueve o "replanta" los commits de una rama a un nuevo punto base.

  • Crea un historial lineal y limpio, fácil de seguir.
  • Perfecto para fusionar ramas locales privadas.
  • Trabajas localmente con ramas privadas. 

  • Antes de hacer un Pull Request.

Es ideal usarlo cuando:

Fusión con git rebase

Estructura básica del comando:

git checkout <rama-destino>
git rebase <rama-origen>

Ejemplo:

¡Advertencia!

Nunca hagas git rebase de commits públicos

Fuente de imagen: Giphy

Estrategias avanzadas

Cherry-pick

Permite elegir commits de una rama por su referencia y añadirlos al HEAD actual de trabajo.

⚠️ Genera commits duplicados ⚠️

Fuente de imagen: Giphy

¿Cómo seleccionar commits específicos?

1. Buscar el commit que se quiere traer a la rama:

git log --oneline <nombre_rama>

3. Pegar el hash copiado del paso anterior en el siguiente comando:

git cherry-pick <hash-commit>

2. Del listado, copiar el hash (compuesto por siete caracteres)

b91eec0 mensaje - commit 4
2cd08fb mensaje - commit 3
cc1ba37 mensaje - commit 2
defd04e mensaje - commit 1

Ejemplo:

Buscar el commit en el listado y copiar su hash.

Pegar el hash en el comando git cherry-pick:

* Como puede observarse en las capturas, d452c19 y 166b876 son distintos hashes del mismo commit

Stash

Permite almacenar temporalmente los cambios cuando necesitas moverte rápidamente a otra rama/contexto para trabajar en otra cosa.

Fuente de imagen: Giphy

Comandos útiles: git stash

a. Guardar el trabajo actual en un stash:

git stash

b. Recuperar el último stash:

git stash pop

c. Ver lista de stashes:

git stash list

En la práctica se vería de la siguiente manera:

Squash

Combina varios commits en uno solo.

Se utiliza cuando se han realizado varios commits pequeños para una característica o corrección de errores.

Fuente de imagen: Pinterest

Diferentes maneras de hacer squash

a. Usando git rebase interactivo, e indicando un rango de commits:

git rebase -i <commits-a-unificar>
git merge --squash <nombre-rama>

b. Usando git merge:

Ejemplo con git rebase -i

Se puede hacer un squash de los tres commits más recientes:

git rebase -i HEAD~3

Ejemplo con git merge --squash

Se puede hacer un squash de una rama en particular:

git merge --squash <nombre-rama>

Reset

Mueve el puntero HEAD y la rama actual a un commit específico.

Tiene tres modos: --soft, --mixed, --hard

Fuente de imagen: Giphy

Deshacer el último commit, manteniendo cambios en el área staging:

git reset --soft HEAD~1

Ejemplos prácticos para cada modo

Deshacer el último commit y remover cambios del área staging:

git reset HEAD~1

* El modo --mixed está configurado por defecto

Deshacer cambios del último commit y eliminar todo (¡CUIDADO con este comando!):

git reset --hard HEAD~1

Revert

Crea un nuevo commit que deshace cambios de commits anteriores.

Fuente de imagen: Ion Litio

Revertir el último commit:

git revert HEAD

Ejemplos prácticos

git revert 8be4b22

Revertir un commit específico:

* Recordatorio: para extraer la versión corta del hash, ejecutar git log --oneline

Restore

Restaura archivos del directorio de trabajo o del área staging. No modifica commits ni el historial.

Fuente de imagen: Pinterest

Descartar cambios en un archivo (directorio de trabajo):

git restore archivo.py

Ejemplos prácticos

git restore --staged archivo.py

Restaurar archivo a una versión específica:

git restore --source=HEAD~1 archivo.py

Descartar cambios en un archivo (área de staging):

Gestión de conflictos

Conflictos en Git

Conflicto por modificación simultánea

1. Ver archivos en conflicto:

git status
<<<<<<< HEAD
def compile_model(model):
  return model.compile(loss="binary_crossentropy")
=======
def compile_model(model):
  return model.compile(
      loss="binary_crossentropy",
      optimizer="adam",
      metrics=["accuracy", "roc_auc", "f1_score"]
  )
>>>>>>> feature/model-compile

2. Identificar marcadores en el archivo:

3. Resolver el conflicto desde el mismo código o desde la terminal.

a. Aceptar cambios entrantes:

Opciones de resolución (desde la terminal)

git checkout --theirs <path/archivo/con/conflicto>

b. Mantener versión actual:

git checkout --ours <path/archivo/con/conflicto>

c. Crear una solución combinada, editando manualmente y luego commitear:

git add <path-archivo>
git commit -m "merge: mensaje de referencia"

a. Si intentabas hacer un git pull/push:

git push origin <nombre-rama>
git pull origin <nombre-rama>

b. Si estabas fusionando ramas:

git merge --continue

4. Continuar con el proceso que se interrumpió debido al conflicto.

c. Si estabas realizando un squash:

git merge --squash <nombre-rama>

Ejemplo:

Conflicto al hacer rebase

1. Leer el mensaje:

git status

Opciones que ofrece git rebase

git rebase --continue

a. Después de resolver el conflicto:

git rebase --abort
git rebase --skip 

b. Cancelar el rebase:

c. Saltar el commit problemático:

Tips importantes

1. Leer los mensajes de Git:

git status # Muestra si hay archivos en conflicto
git diff --check # Verifica existencia de conflictos

2. Usar herramientas visuales (si está configurado):

git mergetools

3. Prevenir conflictos verificando diferencias entre ramas:

git diff <nombre-rama-1>...<nombre-rama-2>

Conflictos en GitHub

Resolver el conflicto...

... y luego, retomar el merge de las ramas.

GitHub 2.0

Pull Requests (PR)

Utilidad de los "PRs"

  • Detectar errores y problemas potenciales antes de fusionar los cambios.
  • Mantener el código limpio y estable.
  • Facilitar la comunicación entre los miembros del equipo.
  • Analizar los cambios y hacer recomendaciones para mejorarlos.

Crear un PR:

Gestión de repositorios

  • Reglas de protección de ramas (branch protection rules).
  • Métricas y análisis.
  • Colaboración avanzada.
  • y mucho más...

Reglas de protección de ramas:

Métricas y análisis:

Network graph

Métricas de uso de GH Actions

Colaboración avanzada:

Tablero de proyectos

Discussions

Otras funcionalidades: GitHub Pages

Bonus

GitHub Actions

GitHub Actions es una plataforma de automatización que permite crear flujos de trabajo personalizado (workflows) directamente en el repositorio.

Estos workflows se activan por eventos de GitHub (push, pull request o de forma programada).

Pueden ejecutar una serie de tareas automatizadas como pruebas, despliegues, o cualquier proceso de CI/CD.

Se definen en archivos YAML dentro del directorio de .github/workflows.

Aplicaremos algunos de los conceptos vistos de Git y de GitHub en un proyecto ficticio.

Demo

Recursos adicionales  📚

¡Muchas gracias! 🥰

[ES] Git & GitHub Avanzado

By Le Wagon LatAm

[ES] Git & GitHub Avanzado

  • 224