5  Desarrollo y Git

El desarrollo moderno requiere herramientas potentes para control de versiones, gestión de repositorios y ejecución de código. Esta sección cubre las herramientas esenciales para cualquier desarrollador profesional.

5.1 git - Control de versiones distribuido

Git es el sistema de control de versiones más usado del mundo, fundamental para cualquier proyecto de desarrollo moderno.

5.1.1 Configuración inicial

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

# Editor por defecto
git config --global core.editor "code --wait"

# Configuraciones útiles
git config --global init.defaultBranch main
git config --global pull.rebase false
git config --global push.default simple

5.1.2 Workflow básico

5.1.2.1 Inicialización y clonado

# Inicializar nuevo repositorio
git init
git init mi-proyecto

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

# Clonar solo historia reciente (más rápido)
git clone --depth 1 https://github.com/usuario/repo.git

5.1.2.2 Área de staging y commits

# Ver estado del repositorio
git status
git status -s  # Formato corto

# Agregar archivos al staging
git add archivo.txt
git add .  # Todos los archivos
git add *.py  # Por patrón
git add -A  # Incluir eliminados

# Commits
git commit -m "Mensaje descriptivo"
git commit -am "Agregar y commitear archivos modificados"
git commit --amend  # Modificar último commit

5.1.3 Branching y merging

5.1.3.1 Gestión de branches

# Listar branches
git branch  # Locales
git branch -r  # Remotos
git branch -a  # Todos

# Crear y cambiar de branch
git branch nueva-feature
git checkout nueva-feature
# O en un comando:
git checkout -b nueva-feature

# Cambiar entre branches
git checkout main
git checkout -  # Branch anterior

# Eliminar branch
git branch -d feature-completada
git branch -D feature-forzar-eliminar  # Forzar

5.1.3.2 Merge strategies

# Merge básico
git checkout main
git merge feature-branch

# Merge sin fast-forward (siempre crea commit de merge)
git merge --no-ff feature-branch

# Squash merge (combina todos los commits en uno)
git merge --squash feature-branch
git commit -m "Feature: descripción completa"

# Rebase (historia lineal)
git checkout feature-branch
git rebase main
git checkout main
git merge feature-branch  # Fast-forward

5.1.4 Historial y navegación

5.1.4.1 Visualización de historia

# Log básico
git log
git log --oneline  # Compacto
git log --graph --oneline --all  # Gráfico

# Historial de un archivo
git log --follow archivo.txt
git log -p archivo.txt  # Con diferencias

# Buscar en commits
git log --grep="fix"  # Por mensaje
git log --author="Juan"  # Por autor
git log --since="2 weeks ago"  # Por fecha

5.1.4.2 Diferencias y comparaciones

# Ver cambios no commiteados
git diff
git diff --staged  # En staging area

# Comparar branches
git diff main..feature-branch
git diff main...feature-branch  # Desde punto común

# Comparar commits específicos
git diff abc123 def456
git diff HEAD~1 HEAD  # Último commit vs anterior

5.1.5 Casos de uso avanzados

5.1.5.1 Trabajo con remotes

# Configurar remotes
git remote add origin https://github.com/usuario/repo.git
git remote -v  # Ver remotes configurados

# Fetch y pull
git fetch origin  # Descargar cambios sin merge
git pull origin main  # Fetch + merge
git pull --rebase origin main  # Fetch + rebase

# Push
git push origin main
git push -u origin feature-branch  # Primera vez
git push --force-with-lease origin main  # Force seguro

5.1.5.2 Stashing (guardado temporal)

# Guardar cambios temporalmente
git stash
git stash push -m "Trabajo en progreso"

# Ver stashes
git stash list

# Aplicar stash
git stash pop  # Aplicar y eliminar
git stash apply  # Aplicar sin eliminar
git stash apply stash@{1}  # Stash específico

# Eliminar stashes
git stash drop stash@{0}
git stash clear  # Todos

5.1.5.3 Revertir cambios

# Descartar cambios no commiteados
git checkout -- archivo.txt
git restore archivo.txt  # Git 2.23+

# Quitar de staging area
git reset HEAD archivo.txt
git restore --staged archivo.txt  # Git 2.23+

# Revertir commits
git revert abc123  # Crear commit que deshace otro
git reset --soft HEAD~1  # Deshacer commit, mantener cambios
git reset --hard HEAD~1  # Deshacer commit y cambios (peligroso)

5.1.6 Workflows de equipo

5.1.6.1 Feature branch workflow

# 1. Crear feature branch desde main actualizado
git checkout main
git pull origin main
git checkout -b feature/nueva-funcionalidad

# 2. Desarrollar y commitear
git add .
git commit -m "feat: implementar nueva funcionalidad"

# 3. Actualizar con cambios de main
git fetch origin
git rebase origin/main

# 4. Push de feature branch
git push -u origin feature/nueva-funcionalidad

# 5. Crear Pull Request en GitHub/GitLab
# 6. Después del merge, limpiar
git checkout main
git pull origin main
git branch -d feature/nueva-funcionalidad

5.1.6.2 Git flow

# Branches principales: main, develop
# Branches de soporte: feature/, release/, hotfix/

# Iniciar feature
git checkout develop
git checkout -b feature/nueva-caracteristica

# Finalizar feature
git checkout develop
git merge --no-ff feature/nueva-caracteristica
git branch -d feature/nueva-caracteristica

# Release branch
git checkout -b release/1.2.0 develop
# Fix bugs, actualizar versión
git checkout main
git merge --no-ff release/1.2.0
git tag -a v1.2.0 -m "Version 1.2.0"
git checkout develop
git merge --no-ff release/1.2.0

5.2 gh - GitHub CLI

La CLI oficial de GitHub permite gestionar repositorios, pull requests, issues y más desde terminal.

5.2.1 Autenticación

# Login interactivo
gh auth login

# Verificar autenticación
gh auth status

# Login con token
echo "ghp_xxxxxxxxxxxx" | gh auth login --with-token

5.2.2 Gestión de repositorios

5.2.2.1 Crear y clonar

# Crear repositorio nuevo
gh repo create mi-proyecto
gh repo create mi-proyecto --public
gh repo create mi-proyecto --private --clone

# Clonar repositorio
gh repo clone usuario/repositorio
gh repo clone https://github.com/usuario/repo

# Ver información del repo
gh repo view
gh repo view usuario/repositorio

5.2.2.2 Gestión básica

# Listar repositorios
gh repo list  # Propios
gh repo list usuario  # De un usuario
gh repo list --limit 50

# Fork de repositorio
gh repo fork usuario/repositorio
gh repo fork usuario/repositorio --clone

# Sincronizar fork
gh repo sync usuario/mi-fork

5.2.3 Pull Requests

5.2.3.1 Crear y gestionar PRs

# Crear PR desde branch actual
gh pr create
gh pr create --title "Nueva feature" --body "Descripción detallada"

# Crear PR con template
gh pr create --template=.github/pull_request_template.md

# Listar PRs
gh pr list
gh pr list --state=open
gh pr list --author=@me

# Ver detalles de PR
gh pr view 123
gh pr view --web 123  # Abrir en navegador

5.2.3.2 Review y merge

# Checkout PR localmente
gh pr checkout 123

# Aprobar PR
gh pr review 123 --approve
gh pr review 123 --approve --body "LGTM! 🚀"

# Solicitar cambios
gh pr review 123 --request-changes --body "Necesita documentación"

# Merge PR
gh pr merge 123
gh pr merge 123 --merge  # Merge commit
gh pr merge 123 --squash  # Squash merge
gh pr merge 123 --rebase  # Rebase merge

5.2.4 Issues

5.2.4.1 Gestión de issues

# Crear issue
gh issue create
gh issue create --title "Bug: error en login" --body "Descripción del bug"

# Listar issues
gh issue list
gh issue list --state=open --assignee=@me
gh issue list --label=bug

# Ver y editar issue
gh issue view 456
gh issue edit 456 --add-label=priority-high
gh issue close 456

5.2.4.2 Plantillas y automation

# Crear issue con template
gh issue create --template=bug_report.md

# Asignar issue
gh issue edit 456 --assignee=usuario

# Comentar en issue
gh issue comment 456 --body "Trabajando en esto"

5.2.5 Actions y CI/CD

# Ver workflows
gh workflow list
gh workflow view ci.yml

# Ver runs
gh run list
gh run view 123456

# Cancelar run
gh run cancel 123456

# Re-ejecutar workflow
gh run rerun 123456

5.2.6 Casos de uso avanzados

5.2.6.1 Automatización con scripts

#!/bin/bash
# Script para crear PR automaticamente

# Verificar que estamos en un branch que no sea main
current_branch=$(git branch --show-current)
if [ "$current_branch" = "main" ]; then
    echo "No puedes crear PR desde main"
    exit 1
fi

# Push del branch actual
git push -u origin "$current_branch"

# Crear PR con información del branch
title=$(echo "$current_branch" | sed 's/-/ /g' | sed 's/feature\///g')
gh pr create --title "$title" --body "Resolves #issue_number"

echo "PR creado: $(gh pr view --json url --jq .url)"

5.2.6.2 Release automation

#!/bin/bash
# Script para crear release automáticamente

version="$1"
if [ -z "$version" ]; then
    echo "Uso: $0 <version>"
    exit 1
fi

# Crear tag
git tag -a "v$version" -m "Version $version"
git push origin "v$version"

# Generar changelog automático
changelog=$(gh api repos/:owner/:repo/releases/generate-notes \
    -f tag_name="v$version" \
    --jq .body)

# Crear release
gh release create "v$version" \
    --title "Release v$version" \
    --notes "$changelog" \
    --draft=false \
    --prerelease=false

echo "Release v$version creado exitosamente!"

5.3 node - JavaScript Runtime

Node.js permite ejecutar JavaScript fuera del navegador, siendo fundamental para desarrollo web moderno.

5.3.1 Gestión de versiones con nvm

# Instalar versión específica
nvm install 18.17.0
nvm install --lts  # Última LTS

# Usar versión específica
nvm use 18.17.0
nvm use --lts

# Ver versiones instaladas
nvm list
nvm list-remote  # Disponibles para instalar

# Establecer versión por defecto
nvm alias default 18.17.0

5.3.2 npm - Node Package Manager

5.3.2.1 Gestión de paquetes

# Inicializar proyecto
npm init
npm init -y  # Con valores por defecto

# Instalar paquetes
npm install express
npm install -D jest  # Como devDependency
npm install -g nodemon  # Global

# Instalar desde package.json
npm install
npm ci  # Para CI/CD (más rápido, determinístico)

5.3.2.2 Scripts y automation

# En package.json
{
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js",
    "test": "jest",
    "build": "webpack --mode=production",
    "lint": "eslint src/",
    "format": "prettier --write src/"
  }
}

# Ejecutar scripts
npm start
npm run dev
npm test
npm run build

5.3.3 Desarrollo con Node.js

5.3.3.1 REPL y debugging

# REPL interactivo
node

# Ejecutar archivo
node app.js

# Debugging
node --inspect app.js
node --inspect-brk app.js  # Pausar en primera línea

# Profiling
node --prof app.js
node --prof-process isolate-*.log

5.3.3.2 Módulos y require

// CommonJS (Node.js tradicional)
const fs = require('fs');
const path = require('path');
const { promisify } = require('util');

// ES Modules (Node.js moderno)
import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';

5.3.4 Casos de uso prácticos

5.3.4.1 Script de automatización

#!/usr/bin/env node
// build-tool.js
const fs = require('fs/promises');
const path = require('path');
const { execSync } = require('child_process');

async function buildProject() {
    console.log('🚀 Iniciando build...');
    
    // Limpiar directorio dist
    await fs.rmdir('./dist', { recursive: true }).catch(() => {});
    await fs.mkdir('./dist', { recursive: true });
    
    // Compilar TypeScript
    console.log('📝 Compilando TypeScript...');
    execSync('tsc --outDir dist');
    
    // Copiar assets
    console.log('📁 Copiando assets...');
    await fs.cp('./src/assets', './dist/assets', { recursive: true });
    
    // Generar package.json para producción
    const pkg = JSON.parse(await fs.readFile('./package.json', 'utf8'));
    const prodPkg = {
        name: pkg.name,
        version: pkg.version,
        dependencies: pkg.dependencies,
        main: 'index.js'
    };
    await fs.writeFile('./dist/package.json', JSON.stringify(prodPkg, null, 2));
    
    console.log('✅ Build completado!');
}

buildProject().catch(console.error);

5.3.4.2 API simple con Express

// server.js
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(helmet());
app.use(cors());
app.use(express.json());

// Logging middleware
app.use((req, res, next) => {
    console.log(`${new Date().toISOString()} ${req.method} ${req.path}`);
    next();
});

// Routes
app.get('/api/health', (req, res) => {
    res.json({ status: 'OK', timestamp: new Date().toISOString() });
});

app.get('/api/users', (req, res) => {
    // Simulación de datos
    res.json([
        { id: 1, name: 'Juan', email: 'juan@example.com' },
        { id: 2, name: 'María', email: 'maria@example.com' }
    ]);
});

// Error handling
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).json({ error: 'Something went wrong!' });
});

app.listen(PORT, () => {
    console.log(`🚀 Server running on http://localhost:${PORT}`);
});

5.4 Workflows integrados

5.4.1 Desarrollo Full-Stack

#!/bin/bash
# Script de desarrollo completo

# 1. Clonar y configurar proyecto
clone_and_setup() {
    gh repo clone mi-org/mi-proyecto
    cd mi-proyecto
    
    # Instalar dependencias
    npm install
    
    # Configurar git hooks
    npx husky install
    
    # Crear branch de desarrollo
    git checkout -b feature/nueva-funcionalidad
}

# 2. Desarrollo con live reload
dev_server() {
    # Terminal 1: Backend
    npm run dev:server &
    
    # Terminal 2: Frontend
    npm run dev:client &
    
    # Terminal 3: Tests en watch mode
    npm run test:watch &
    
    wait
}

# 3. Pre-commit workflow
pre_commit() {
    # Linting
    npm run lint:fix
    
    # Formateo
    npm run format
    
    # Tests
    npm test
    
    # Type checking
    npm run type-check
    
    if [ $? -eq 0 ]; then
        echo "✅ Todo OK, procediendo con commit"
        git add .
        git commit -m "$1"
    else
        echo "❌ Errores encontrados, revisar antes de commit"
        exit 1
    fi
}

# 4. Deploy workflow
deploy() {
    # Build de producción
    npm run build
    
    # Push y crear PR
    git push -u origin "$(git branch --show-current)"
    gh pr create --title "Deploy: $(date +%Y-%m-%d)" --body "Release automático"
    
    # Esperar aprobación y merge
    pr_number=$(gh pr view --json number --jq .number)
    echo "PR #$pr_number creado. Esperando aprobación..."
}

5.4.2 Git workflow avanzado

#!/bin/bash
# Workflow completo de Git con integración GitHub

git_workflow() {
    local issue_number="$1"
    local feature_name="$2"
    
    if [ -z "$issue_number" ] || [ -z "$feature_name" ]; then
        echo "Uso: git_workflow <issue_number> <feature_name>"
        return 1
    fi
    
    # 1. Actualizar main
    git checkout main
    git pull origin main
    
    # 2. Crear branch desde issue
    branch_name="feature/${issue_number}-${feature_name}"
    git checkout -b "$branch_name"
    
    # 3. Configurar tracking
    git push -u origin "$branch_name"
    
    # 4. Asociar con issue
    gh issue edit "$issue_number" --add-assignee @me
    gh issue comment "$issue_number" --body "🚧 Trabajando en branch: $branch_name"
    
    echo "✅ Branch $branch_name creado y asociado con issue #$issue_number"
    echo "💡 Cuando termines, ejecuta: finish_feature $issue_number"
}

finish_feature() {
    local issue_number="$1"
    
    # 1. Push final
    git push origin "$(git branch --show-current)"
    
    # 2. Crear PR que cierre el issue
    gh pr create \
        --title "Resolve #$issue_number" \
        --body "Closes #$issue_number" \
        --reviewer team-leads
    
    # 3. Comentar en issue
    pr_url=$(gh pr view --json url --jq .url)
    gh issue comment "$issue_number" --body "🎉 PR creado: $pr_url"
    
    echo "✅ PR creado. Revisa en: $pr_url"
}

# Usar: git_workflow 123 user-authentication
Tips para desarrollo eficiente
  • Configura aliases de Git para comandos frecuentes
  • Usa gh para automatizar workflows de GitHub
  • Combina git hooks con husky para validaciones automáticas
  • Mantén commits atómicos y mensajes descriptivos siguiendo Conventional Commits
Mejores prácticas
  • Nunca hagas push --force en branches compartidos
  • Usa --force-with-lease en lugar de --force cuando sea necesario
  • Mantén historial limpio con rebase interactivo antes de merge
  • Configura firma GPG para commits verificados

En el próximo capítulo exploraremos herramientas de multimedia para procesamiento de video, audio e imágenes.