Git fundamentos
Git es un sistema de control de versiones. Cada cambio que haces queda registrado como un snapshot (commit). Puedes volver a cualquier punto, comparar versiones, trabajar en paralelo con ramas, y colaborar con otros sin pisar el trabajo de nadie.
Si no usas Git, cada cambio es un riesgo. Un archivo borrado, un bug introducido, un deploy fallido. Con Git, todo es reversible.
Comandos básicos
# Inicializar un repositorio nuevo
git init
# Clonar un repositorio existente
git clone https://github.com/tu-usuario/tu-proyecto.git
# Ver el estado (que ha cambiado desde el ultimo commit)
git status
# Ver los cambios exactos (diff)
git diff # Cambios no staged
git diff --staged # Cambios staged (listos para commit)
# Agregar archivos al staging area
git add src/api/routes.py # Un archivo específico
git add src/api/ # Todo el directorio
git add . # Todo (cuidado: revisa antes con git status)
# Crear un commit (snapshot permanente)
git commit -m "feat: add task creation endpoint with Pydantic validation"
# Ver historial de commits
git log --oneline # Vista compacta
git log --oneline --graph # Con grafico de ramas
git log -5 # Ultimos 5 commits
Ramas (branches)
Las ramas permiten trabajar en funcionalidades nuevas sin afectar al código principal. Cuando terminas, fusionas (merge) la rama.
# Crear y cambiar a una nueva rama
git checkout -b feature/user-auth
# Listar ramas
git branch # Locales
git branch -a # Locales + remotas
# Cambiar de rama
git checkout main
# Fusionar una rama en la actual
git checkout main
git merge feature/user-auth
# Eliminar rama (después de merge)
git branch -d feature/user-auth
Merge vs Rebase
Dos formas de integrar cambios de una rama a otra:
# MERGE: crea un commit de fusion. Preserva el historial completo.
git checkout main
git merge feature/user-auth
# Resultado: commit de merge que une las dos lineas
# REBASE: reescribe el historial. línea limpia, sin bifurcaciones.
git checkout feature/user-auth
git rebase main
git checkout main
git merge feature/user-auth # Fast-forward, sin commit de merge
Cuando usar merge: en equipo, cuando quieres preservar quien hizo que y cuando. Es la opción segura.
Cuando usar rebase: trabajando solo, cuando quieres un historial limpio y lineal. más fácil de leer.
Regla critica: NUNCA hagas rebase de ramas que ya están en remoto y que otros pueden estar usando. Rebase reescribe el historial, y eso rompe el trabajo de los demás.
Resolver conflictos
# Si un merge tiene conflictos, Git marca los archivos
# Abre el archivo y veras algo asi:
<<<<<<< HEAD
def get_user(user_id: str):
return db.users.find_one({"id": user_id})
=======
def get_user(user_id: str) -> User:
result = db.users.find_one({"id": user_id})
return User(**result) if result else None
>>>>>>> feature/user-auth
# Decide que versión quieres (o combina ambas), elimina los marcadores,
# y luego:
git add src/services/user_service.py
git commit -m "fix: resolve merge conflict in get_user"
GitHub essentials
GitHub no es solo donde guardas código. Es tu plataforma completa de desarrollo: repositorios, pull requests, issues, projects, discussions, actions, y pages.
Pull Requests (PRs)
Un PR es una propuesta de cambios. Antes de que el código llegue a main, alguien (o un bot de CI) lo revisa.
# Flujo completo con gh CLI
# 1. Crear rama y hacer cambios
git checkout -b feature/task-api
# ... hacer cambios y commits ...
# 2. Push a remoto
git push -u origin feature/task-api
# 3. Crear PR
gh pr create \
--title "feat: add task CRUD endpoints" \
--body "## Summary
- Add POST /api/v1/tasks with Pydantic validation
- Add GET /api/v1/tasks with pagination
- Add PATCH /api/v1/tasks/{id}
- Add DELETE /api/v1/tasks/{id} (soft delete)
## Test plan
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual test with Swagger UI"
# 4. Ver PRs abiertos
gh pr list
# 5. Ver el diff de un PR
gh pr diff 42
# 6. Revisar y aprobar
gh pr review 42 --approve --body "LGTM, tests pasan"
# 7. Mergear
gh pr merge 42 --squash --delete-branch
Issues y Projects
# Crear un issue
gh issue create \
--title "Bug: tasks endpoint returns 500 on empty title" \
--body "Steps to reproduce: POST /api/v1/tasks with empty title"
# Listar issues
gh issue list --state open
# Cerrar un issue (automático con commit message)
git commit -m "fix: validate task title is not empty
Closes #42"
Branching strategy
Trunk-based development (developer solo o equipo pequeño)
Una rama principal: main. Feature branches cortas (horas, no semanas). Merge directo a main con PR. Deploy continuo desde main.
# Flujo trunk-based
git checkout -b fix/empty-title-validation # Branch corta
# ... cambios ...
git commit -m "fix: validate task title is not empty"
git push -u origin fix/empty-title-validation
gh pr create --title "fix: validate task title"
# CI pasa > review > merge > deploy automático
Git Flow (equipo grande o releases programados)
# Ramas permanentes
main # producción (siempre deployable)
develop # integración (donde se merge todo)
# Ramas temporales
feature/* # Nueva funcionalidad (sale de develop, vuelve a develop)
release/* # Preparar versión (sale de develop, va a main y develop)
hotfix/* # Parche urgente en producción (sale de main, va a main y develop)
# Ejemplo: nueva funcionalidad
git checkout develop
git checkout -b feature/user-roles
# ... desarrollo ...
git checkout develop
git merge feature/user-roles
# Ejemplo: release
git checkout develop
git checkout -b release/2.1.0
# ... ajustes finales, versión bump ...
git checkout main
git merge release/2.1.0
git tag v2.1.0
git checkout develop
git merge release/2.1.0
Recomendación
Si eres developer solo o equipo de 2-3, usa trunk-based. Si el equipo crece a 5+ personas o necesitas releases planificados, migra a Git Flow. No empieces con Git Flow para un proyecto personal.
CI/CD con GitHub Actions
CI/CD automatiza lo que harias a mano: comprobar que el código está limpio, pasar tests, construir el artefacto, y deployar. Se dispara automáticamente con cada push o PR.
Workflow completo y real
# .github/workflows/ci.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
PYTHON_VERSION: "3.11"
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-versión: ${{ env.PYTHON_VERSION }}
- name: Install linter
run: pip install ruff
- name: Check format
run: ruff format --check src/
- name: Check lint
run: ruff check src/
test:
needs: lint # solo corre si lint pasa
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-versión: ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install pytest pytest-cov pytest-asyncio
- name: Run tests
run: pytest tests/ -v --cov=src --cov-report=term --cov-fail-under=70
- name: Upload coverage
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: htmlcov/
security:
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Historial completo para gitleaks
- name: Run gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
deploy:
needs: [test, security] # solo si tests Y security pasan
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
command: pages deploy dist --project-name=mi-proyecto
Anatomía del workflow
- on: cuando se dispara (push a main, PR a main)
- jobs: tareas independientes que corren en paralelo (a menos que uses
needs) - needs: dependencias entre jobs.
testespera a quelintpase. - if: condiciones. Deploy solo en push a main, no en PRs.
- secrets: variables sensibles configuradas en Settings > Secrets de GitHub. NUNCA en el YAML.
Workflow para Next.js (frontend)
# .github/workflows/frontend.yml
name: Frontend CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-versión: 20
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run build
- run: npm test -- --coverage
GitHub Pages: hosting gratis
GitHub Pages te da hosting gratuito para sitios estaticos. Perfecto para documentación, portfolios, landing pages, y blogs estaticos.
# Opcion 1: Deploy automático con Actions
# .github/workflows/deploy-pages.yml
name: Deploy to GitHub Pages
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-versión: 20
- run: npm ci && npm run build
- uses: actions/configure-pages@v4
- uses: actions/upload-pages-artifact@v3
with:
path: './dist'
- id: deployment
uses: actions/deploy-pages@v4
# Opcion 2: rama gh-pages (clasica)
# Settings > Pages > Source: Deploy from a branch > gh-pages
# Custom domain
# 1. Crear archivo CNAME en la raiz del site con tu dominio
echo "mi-proyecto.com" > dist/CNAME
# 2. Configurar DNS: CNAME apuntando a tu-usuario.github.io
GitHub Copilot vs Claude Code
Son herramientas complementarias, no competidoras. Cada una tiene un punto fuerte diferente.
GitHub Copilot
- Mejor para: autocompletar código en tiempo real mientras escribes en el editor
- Contexto: el archivo actual y archivos abiertos en el editor
- integración: VS Code, JetBrains, Neovim
- Ideal para: escribir código nuevo, completar funciones, generar tests inline
Claude Code
- Mejor para: tareas complejas que afectan múltiples archivos, refactoring, arquitectura
- Contexto: todo el repositorio, git history, archivos de configuración
- integración: terminal, cualquier editor indirectamente
- Ideal para: refactors grandes, crear componentes completos, CI/CD, debugging
Combinación ganadora
Usa Copilot mientras escribes código nuevo (autocompletar rápido). Usa Claude Code para tareas de arquitectura, refactoring multi-archivo, crear PRs, y debugging complejo. Son complementarios.
Preguntas frecuentes
¿Qué diferencia hay entre Git y GitHub?
Git es el sistema de control de versiones que registra cambios en local. GitHub aloja repositorios Git y añade colaboración mediante pull requests, issues, revisiones y automatizaciones.
¿Debo usar merge o rebase?
Merge es la opción prudente para integrar trabajo compartido porque conserva la historia. Rebase resulta útil para ordenar una rama propia antes de publicarla, pero no debe reescribir una historia que otras personas ya usan.
¿Qué estrategia de ramas conviene a un equipo pequeño?
Una rama principal protegida y ramas de trabajo breves suele ser suficiente. Cada cambio entra mediante pull request, pasa las comprobaciones automáticas y se integra cuando el diff ha sido revisado.
¿Qué debe comprobar una acción de integración continua?
Como mínimo debe instalar dependencias de forma reproducible, ejecutar las comprobaciones relevantes y fallar con un mensaje claro. El despliegue debe depender del éxito de esas comprobaciones.
¿GitHub Pages sirve para cualquier aplicación?
Está pensado para contenido estático. Una aplicación que necesita ejecutar lógica de servidor, procesos persistentes o una base de datos requiere un backend desplegado en otra infraestructura.
¿Copilot o Claude Code sustituyen la revisión humana?
No. Ambas herramientas pueden proponer código o explicar un repositorio, pero la persona responsable debe revisar el diff, comprobar los supuestos, ejecutar validaciones y decidir qué llega al historial.
📚 Aprende más en el curso
Este artículo complementa el Módulo M16: Git y repositorios con IA. Incluye vídeo, quiz, flashcards con repaso espaciado y proyecto práctico.