Git

Una herramienta esencial para el desarrollo de software

Agenda

  1. Introducción a Git
  2. Conceptos básicos y áreas de trabajo
  3. Configuración y comandos esenciales
  4. Trabajo con ramas y resolución de conflictos
  5. Integración con GitHub
    • Autenticación (HTTPS y SSH)
    • GitHub CLI
  6. Flujos de trabajo comunes
    • Gitflow vs Trunk-based
    • Feature branches y Pull Requests
    • Feature flags
  7. Modelando la historia
    • Merge vs Rebase
    • Reset y reflog
  8. Conventional Commits
  9. Demo práctica
  10. Call to Action: Buenas Prácticas

1. Introducción a Git

"Los sistemas de control de versiones no son sobre archivos, son sobre los cambios a los archivos"

Git es un sistema de control de versiones distribuido diseñado para:

  • Rastrear cambios en archivos
  • Coordinar el trabajo entre múltiples personas
  • Mantener un historial completo del proyecto
  • Permitir volver a estados anteriores

Historia Breve

  • Creado por Linus Torvalds en 2005 para el desarrollo del kernel de Linux
  • Surgió como alternativa a herramientas propietarias y centralizadas
  • Hoy es el estándar de la industria para control de versiones

Diferencias con otros sistemas

Sistemas centralizados (SVN, CVS):

  • Dependen de un servidor central
  • Requieren conexión constante
  • Operaciones más lentas

Git (Distribuido):

  • Cada desarrollador tiene una copia completa del repositorio
  • Permite trabajo sin conexión
  • Mayor velocidad y flexibilidad

2. Conceptos básicos de Git

Repositorio:

  1. Repositorio: Colección de archivos y su historial de cambios
  2. Local: En tu máquina personal
  3. Remoto: Alojado en un servidor (GitHub, GitLab, etc.)

Ciclo de trabajo básico:

  1. Modificar archivos en tu directorio de trabajo
  2. Seleccionar archivos para la próxima versión (staging)
  3. Confirmar los cambios (commit)
  4. Sincronizar con repositorios remotos (push/pull)

Áreas de trabajo en Git

  • Working directory: Donde modificas tus archivos
  • Staging area (index): Preparación para el próximo commit
  • Local repository: Historial de commits en tu máquina
  • Remote repository: Versión compartida en el servidor

3. Configuración y comandos esenciales

Configuración inicial

# Configuración global
git config --global user.name "Tu Nombre"
git config --global user.email "tu.email@ejemplo.com"

# Configuración del repositorio actual
git config user.name "Tu Nombre"
git config user.email "tu.email@ejemplo.com"

Iniciar un repositorio

# Crear un nuevo repositorio
git init

# Clonar un repositorio existente
git clone https://github.com/usuario/repositorio.git

Comandos básicos

# Ver estado de archivos
git status

# Añadir archivos al staging area
git add archivo.txt    # Archivo específico
git add .              # Todos los archivos

# Confirmar cambios
git commit -m "Mensaje descriptivo del cambio"
git commit -a -m "Añadir y confirmar en un paso"

# Ver historial de commits
git log
git log --oneline      # Formato resumido
git log --graph        # Con representación gráfica

4. Trabajo con ramas (branches)

  • Las ramas permiten desarrollar funcionalidades aisladas
  • Facilitan el trabajo en paralelo
  • Permiten experimentar sin afectar el código principal

Comandos para ramas

# Ver ramas existentes
git branch

# Crear nueva rama
git branch nueva-funcionalidad

# Cambiar a una rama
git checkout nueva-funcionalidad
git switch nueva-funcionalidad    # Git moderno

# Crear y cambiar en un paso
git checkout -b nueva-funcionalidad

Fusionar y eliminar ramas

# Fusionar ramas
git checkout main
git merge nueva-funcionalidad

# Eliminar rama
git branch -d nueva-funcionalidad    # Si ya está fusionada
git branch -D nueva-funcionalidad    # Forzar eliminación

Resolución de conflictos

Los conflictos ocurren cuando Git no puede resolver automáticamente las diferencias entre ramas:

  1. Git marca los conflictos en los archivos
<<<<<<< HEAD
Cambios en la rama actual
=======
Cambios en la rama que estás fusionando
>>>>>>> rama-a-fusionar
  1. Edita manualmente los archivos para resolver
  2. Añade los archivos resueltos con git add
  3. Completa el merge con git commit

5. Integración con GitHub

Autenticación con HTTPS

# Clonar repositorio con HTTPS
git clone https://github.com/usuario/repo.git

# GitHub solicitará credenciales en cada operación remota
# Recomendado: Configurar credential helper
git config --global credential.helper cache   # Temporal
git config --global credential.helper store    # Permanente

Tokens de acceso personal

  • Más seguros que contraseñas
  • Se generan en GitHub > Settings > Developer settings > Personal access tokens
  • Se usan como contraseña al autenticarse

Autenticación con SSH

  1. Generar clave SSH (si no la tienes)

    ssh-keygen -t ed25519 -C "tu.email@ejemplo.com"
    
  2. Añadir clave al ssh-agent

    eval "$(ssh-agent -s)"
    ssh-add ~/.ssh/id_ed25519
    
  3. Añadir clave pública a GitHub

    • Copiar contenido de ~/.ssh/id_ed25519.pub
    • GitHub > Settings > SSH and GPG keys > New SSH key
  4. Clonar usando SSH

    git clone git@github.com:usuario/repo.git
    

GitHub CLI

Herramienta oficial de línea de comandos para GitHub:

Instalación

# Seguir instrucciones según sistema operativo
# https://github.com/cli/cli#installation

Autenticación

gh auth login

Comandos útiles

# Clonar repositorio
gh repo clone usuario/repo

# Crear pull request
gh pr create

# Ver y revisar pull requests
gh pr list
gh pr checkout número
gh pr view número

# Crear issues
gh issue create

Repositorios remotos

# Ver repositorios remotos
git remote -v

# Añadir repositorio remoto
git remote add origin https://github.com/usuario/repo.git

# Eliminar repositorio remoto
git remote remove origin

¿Qué es upstream?

  • origin: Apunta a tu fork o copia del repositorio
  • upstream: Apunta al repositorio original/principal
# Añadir upstream
git remote add upstream https://github.com/original/repo.git
  
# Obtener cambios del upstream
git fetch upstream
git merge upstream/main

Comandos para colaboración

# Obtener cambios sin integrarlos
git fetch origin

# Obtener e integrar cambios
git pull origin main

# Enviar cambios locales al remoto
git push origin main

# Establecer tracking para simplificar comandos
git push -u origin feature    # Después solo: git push

6. Flujos de trabajo comunes

Gitflow

  • main/master: Código de producción estable
  • develop: Integraciones para próxima versión
  • feature/*: Funcionalidades específicas
  • release/x.y: Preparación para lanzamiento
  • hotfix/*: Correcciones urgentes

Trunk-based development

  • Todos trabajan en la rama principal
  • Commits pequeños y frecuentes
  • Uso de feature flags para ocultar funcionalidades incompletas
  • Integración continua constante

Feature branches y Pull Requests

Proceso típico:

  1. Crear rama desde main/develop
git checkout -b feature/nueva-funcionalidad
  1. Desarrollar y commitear cambios
git add .
git commit -m "feat: implementa nueva funcionalidad"
  1. Enviar rama al remoto
git push -u origin feature/nueva-funcionalidad
  1. Crear Pull Request en GitHub/GitLab
  2. Code review, discusión y aprobación
  3. Merge a la rama principal

Feature Flags

  • Permiten activar/desactivar funcionalidades sin cambios de código
  • Útiles para pruebas A/B, lanzamientos graduales y integración continua

Ejemplos:

// Simple, basado en variables de entorno
if (process.env.FEATURE_NEW_UI === 'true') {
  // Mostrar nueva interfaz
} else {
  // Mostrar interfaz antigua
}

// Basado en usuarios
if (userGroups.includes('beta-testers')) {
  // Mostrar funcionalidad beta
}

// Porcentaje de usuarios
if (Math.random() < 0.1) { // 10% de usuarios
  // Mostrar nueva funcionalidad
}

Feature Flags (implementaciones)

Opciones para gestionar feature flags:

  1. Simples:
    • Variables de entorno
    • Archivos de configuración
  1. Avanzadas:
    • Libraries: Unleash, LaunchDarkly, Flipper
    • Servicios en la nube
// Ejemplo con biblioteca
import { initializeClient } from 'feature-flag-service';

const client = initializeClient('api-key');

if (client.isEnabled('new-payment-method')) {
  // Mostrar nuevo método de pago
}

7. Modelando la historia

Merge: El "Registro Histórico"

  • Conserva toda la historia, incluyendo la bifurcación y la unión
  • Mantiene contexto completo
  • Puede generar historiales complicados
git checkout main
git merge feature/nueva-funcionalidad

Rebase: La "Historia Limpia"

  • Reescribe la historia para que parezca lineal
  • Crea historiales más limpios
  • Puede dificultar la colaboración si no se usa correctamente
git checkout feature/nueva-funcionalidad
git rebase main

El puntero HEAD y el estado del repositorio

¿Qué es HEAD?

  • HEAD es un puntero especial que indica el commit actualmente activo
  • Normalmente HEAD apunta a la última confirmación de la rama actual
  • Es esencial para entender dónde estás en el historial de Git
# Ver a qué apunta HEAD
git rev-parse HEAD

# Ver historial con ubicación de HEAD
git log --oneline --decorate

Estados de HEAD

  1. HEAD normal: Apunta a una rama

    HEAD -> main -> commit A
    
  2. Detached HEAD: Apunta directamente a un commit

    HEAD -> commit C (no rama)
    
    • Ocurre al hacer checkout a un commit específico
    • Los cambios no se guardan en ninguna rama
    • Útil para explorar el historial, peligroso para desarrollo activo

Comandos modernos de Git

git checkout vs git switch vs git restore

git checkout

  • Comando multifunción (tradicional):
  # Cambiar de rama
  git checkout rama-destino
  
  # Crear y cambiar a nueva rama
  git checkout -b nueva-rama
  
  # Restaurar archivos desde HEAD
  git checkout -- archivo.txt
  
  # Moverse a un commit específico (¡crea detached HEAD!)
  git checkout abc123

git switch

  • Comando específico para cambiar ramas (Git 2.23+):
  # Cambiar de rama
  git switch rama-destino
  
  # Crear y cambiar a nueva rama
  git switch -c nueva-rama
  
  # Regresar a la rama anterior
  git switch -

git restore

  • Comando específico para restaurar archivos (Git 2.23+):
  # Descartar cambios en working directory
  git restore archivo.txt
  
  # Descartar cambios en staging area
  git restore --staged archivo.txt
  
  # Restaurar a una versión específica
  git restore --source=HEAD~1 archivo.txt

Escenarios de Detached HEAD

¿Cuando ocurre?

  • Al hacer checkout a un commit específico:
  git checkout abc123
  • Al hacer checkout a una etiqueta:
  git checkout v1.0.0

Precauciones

  • Los cambios y commits realizados en estado detached HEAD pueden perderse
  • Git advierte sobre este estado con un mensaje claro

Cómo salir de Detached HEAD

  1. Sin cambios: Simplemente regresa a una rama
  git checkout main
  1. Con cambios que quieres conservar:
  # Crear una nueva rama donde estás
  git branch nueva-rama-backup
  
  # Cambiar a la nueva rama
  git checkout nueva-rama-backup

Rebase interactivo

Poderosa herramienta para editar la historia antes de integrarla:

git rebase -i HEAD~3  # Editar los últimos 3 commits

Opciones disponibles:

  • pick: mantener el commit
  • reword: cambiar mensaje
  • edit: modificar contenido
  • squash: combinar con commit anterior
  • fixup: combinar y descartar mensaje
  • drop: eliminar commit

Útil para limpiar la historia antes de hacer PR.

Git reset

Permite mover HEAD y la rama actual a un commit específico:

Modos:

  • --soft: Mantiene cambios en staging
  git reset --soft HEAD~1  # Deshacer último commit, conservar cambios
  • --mixed (default): Mantiene cambios en working directory
  git reset HEAD~1  # Deshacer último commit y staging
  • --hard: Elimina cambios completamente
  git reset --hard HEAD~1  # Eliminar último commit y cambios

Git reflog: Salvavidas

Registra todos los movimientos de HEAD, útil para recuperar commits "perdidos":

# Ver historial de referencias
git reflog

# Recuperar commit eliminado
git checkout <hash-del-commit>
git branch nueva-rama  # Para preservar el commit recuperado

8. Conventional Commits

Especificación para dar estructura a los mensajes de commit:

<tipo>[ámbito opcional]: <descripción>

[cuerpo opcional]

[notas de pie opcionales]

Tipos principales:

  • feat: Nueva funcionalidad
  • fix: Corrección de error
  • docs: Cambios en documentación
  • style: Cambios de formato
  • refactor: Cambios que no corrigen ni añaden
  • test: Cambios en pruebas
  • chore: Tareas de mantenimiento

Beneficios de Conventional Commits

  1. Generación automática de changelogs
  2. Determinación semántica de versiones
    • feat: incrementa versión menor (1.0.0 → 1.1.0)
    • fix: incrementa versión de parche (1.0.0 → 1.0.1)
    • feat! o BREAKING CHANGE: incrementa versión mayor (1.0.0 → 2.0.0)
  3. Comunicación clara de la naturaleza de los cambios
  4. Facilita la colaboración y revisión de código
git commit -m "feat(auth): implementa autenticación con Google"
git commit -m "fix(ui): corrige alineación en pantallas pequeñas"

9. Demo práctica

Escenario: Desarrollo de una funcionalidad con feature flag

Paso 1: Configuración inicial

# Configurar Git y clonar repositorio
git config --global user.name "Tu Nombre"
git config --global user.email "tu@email.com"
git clone https://github.com/usuario/proyecto-demo.git
cd proyecto-demo

Paso 2: Crear rama para la funcionalidad

# Crear y cambiar a nueva rama
git checkout -b feature/nueva-api

Demo práctica (continuación)

Paso 3: Implementar con feature flag

// archivo: features.js
const FEATURES = {
  NUEVA_API: process.env.FEATURE_NUEVA_API === 'true'
};

// archivo: api.js
if (FEATURES.NUEVA_API) {
  // Implementación nueva
} else {
  // Implementación antigua
}

Paso 4: Commitear siguiendo conventional commits

git add features.js api.js
git commit -m "feat(api): implementa nueva API con feature flag"

Demo práctica (continuación)

Paso 5: Enviar cambios y crear PR

git push -u origin feature/nueva-api

# Con GitHub CLI
gh pr create --title "Implementa nueva API" --body "Esta PR incluye la nueva API protegida por feature flag"

Paso 6: Después de la aprobación, actualizar y fusionar

git checkout main
git pull
git merge feature/nueva-api
git push

10. Call to Action: Buenas Prácticas

Repository management & CI Automatization

En nuestra organización hemos establecido lineamientos oficiales para:

  • Control estricto de versiones
  • Flujos de trabajo con Git
  • Convenciones de commits
  • Proceso CI/CD
  • Integración con SonarQube
  • Métricas y umbrales de calidad

Consulta el documento completo en nuestro repositorio:

Preguntas frecuentes

  1. ¿Cuándo usar merge vs. rebase?

    • Merge: Para integraciones finales y cuando la historia bifurcada es importante
    • Rebase: Para mantener tu rama actualizada antes de un PR
  2. ¿Cómo recuperar cambios perdidos?

    • Usar git reflog para encontrar y recuperar commits "perdidos"
  3. ¿Cómo resolver conflictos complejos?

    • Herramientas visuales como VSCode, GitKraken
    • Resolver por partes pequeñas

¡Gracias!

Recursos adicionales:

Contacto:

Made with Slides.com