// 01 — QUÉ ES GIT

Qué es Git

Git es un sistema de control de versiones distribuido. Guarda el historial completo de cambios de un proyecto — quién cambió qué, cuándo y por qué. GitHub es la plataforma en la nube que aloja repositorios Git y añade colaboración: Pull Requests, revisiones de código y CI/CD.

📸
Commit = snapshot
Foto del proyecto en un momento. Inmutable, trazable, reversible.
Rama = línea paralela
Desarrollar sin tocar lo que ya funciona. Aislar cada tarea o bug.
🔀
Merge = unir trabajo
Integrar cambios de una rama a otra. Git detecta y resuelve conflictos.
📋
PR = revisión de código
Propuesta de cambio. Permite revisión, comentarios y aprobación antes del merge.
💡
Git ≠ GitHubGit es el software que corre en tu máquina. GitHub es el servicio en la nube. Puedes usar Git sin GitHub, pero GitHub sin Git no existe. GitHub Desktop es una interfaz gráfica para Git que facilita las operaciones más frecuentes sin escribir comandos.

// 02 — CONFIGURACIÓN INICIAL

Configuración Inicial

Antes de hacer el primer commit, Git necesita saber quién eres. Esta información aparece en cada commit del historial — usa tu nombre real y el correo de tu cuenta GitHub.

🖥️ GitHub Desktop
GitHub Desktop ya configura tu identidad automáticamente al iniciar sesión con tu cuenta GitHub.

Verificar: File → Options → Git
Ahí aparecen tu nombre y correo configurados.
⌨️ Terminal
# Configuración global (una sola vez en tu máquina) git config --global user.name "Tu Nombre" git config --global user.email "[email protected]" git config --global core.editor "code --wait" # VS Code # Verificar configuración git config --list
clonar el repositorio VLIMCLI
# Clonar el repositorio desde GitHub
git clone https://github.com/vlim/erp-carniceria.git
cd erp-carniceria

# Verificar estado y ramas disponibles
git status                      # estado del working tree
git branch                      # ramas locales (solo verás main)
git branch -a                   # ramas locales Y remotas

# Obtener la rama dev (después de clonar, no existe localmente)
git checkout -b dev origin/dev  # crea rama dev local vinculada al remoto

# Alternativa moderna
git switch dev                   # si ya existe localmente
git switch -c dev origin/dev   # si no existe aún
🏢
En VLIM: siempre trabaja desde devAl incorporarte al proyecto o abrir GitHub Desktop por primera vez, asegúrate de estar en la rama dev — no en main. Desde dev crearás tus ramas feature. Nunca desde main.

// 03 — COMMITS Y STAGING

Commits y Staging

El flujo básico de Git es: modificar archivos → agregar al staging area (preparar) → confirmar con commit. El staging te permite elegir exactamente qué cambios van en cada commit.

🖥️ GitHub Desktop
En el panel izquierdo verás todos los archivos modificados con checkboxes.

Marcar = agregar al staging
✏️ Escribir mensaje en el campo Summary
🔵 Clic en Commit to [rama]

Para subir: botón Push origin (arriba)
⌨️ Terminal
git add . # agregar todo git add src/ventas.ts # archivo específico git add src/ # carpeta completa git status # ver qué está en staging git diff --staged # ver cambios en staging git commit -m "feat: agregar módulo de ventas" git push origin feature/ventas
convención de mensajes de commit — Conventional CommitsBUENAS PRÁCTICAS
# Formato: tipo(scope): descripción breve en imperativo
#          [línea vacía]
#          Cuerpo opcional (qué y por qué, no cómo)

# Tipos principales:
feat:     # Nueva funcionalidad
fix:      # Corrección de bug
refactor: # Refactorización sin cambio de comportamiento
test:     # Agregar o modificar tests
docs:     # Documentación
style:    # Formato, espacios (sin cambio lógico)
chore:    # Tareas de mantenimiento, dependencias
ci:       # Cambios en CI/CD

# Ejemplos buenos ✅
git commit -m "feat(ventas): agregar descuento por volumen"
git commit -m "fix(auth): corregir expiración de sesión en cajero"
git commit -m "refactor(inventario): extraer lógica de stock a servicio"
git commit -m "docs: actualizar README con instrucciones de Docker"

# Ejemplos malos ❌
# git commit -m "cambios"
# git commit -m "arreglos varios"
# git commit -m "WIP"
# git commit -m "fixed stuff"

// 04 — ARQUITECTURA DE RAMAS VLIM

Arquitectura de Ramas VLIM

En VLIM usamos tres tipos de ramas con roles muy definidos. Nadie hace push directo a main ni a dev — todo pasa por Pull Request. Esta regla se enforcea con Branch Protection en GitHub.

main ────────────────────────────────────────────────────────► producción ▲ ▲ │ PR Sprint 1 (merge --no-ff) │ PR Sprint 2 │ │ dev ───┼──────────────────────────────────────────┼──────────► integración ▲ ▲ ▲ ▲ ▲ ▲ │ PR │ PR │ PR │ PR │ PR │ PR │ │ │ │ │ │ feat/A──┘ feat/B──┘ feat/C──┘ feat/D──┘ feat/E──┘ fix/F───┘ (Ana) (Bob) (Carlos) (Diana) (Ana) (Bob)
RamaRolQuién hace pushRegla
main 🔴 Producción — código estable siempre listo para deploy Nadie directamente Solo PR desde dev al cierre del Sprint
dev 🔵 Integración — todas las features del Sprint se van aquí Nadie directamente Solo PR desde feature/*
feature/nombre 🟢 Trabajo individual — una tarea, un bug, una mejora El desarrollador dueño Se crea desde dev, se elimina al mergearse
📏
Nombres de ramas — convención VLIM feature/nombre-de-la-tarea → nueva funcionalidad
fix/descripcion-del-bug → corrección de bug
refactor/modulo-afectado → refactorización
hotfix/descripcion → corrección urgente en producción

Usa solo minúsculas y guiones. Sin espacios, sin tildes, sin caracteres especiales.
Ejemplos: feature/modulo-ventas, fix/validacion-stock, hotfix/login-cajero

// 05 — FEATURE → PR → DEV

Feature → PR → dev

El ciclo completo de un desarrollador VLIM: desde recibir una tarea hasta que su código queda integrado en dev. Cada paso está cubierto tanto en GitHub Desktop como en la terminal.

1
Actualizar dev antes de empezar
Siempre empieza con dev actualizado — así tu branch parte del código más reciente y evitas conflictos después.
🖥️ GitHub Desktop
1. Current Branch → seleccionar dev
2. Clic en Fetch origin (arriba a la derecha)
3. Si hay cambios: clic en Pull origin
⌨️ Terminal
git checkout dev git pull origin dev
2
Crear la rama feature desde dev
Nombrar la rama con el prefijo correcto y descripción en kebab-case.
🖥️ GitHub Desktop
1. Menú Branch → New Branch (o Ctrl+Shift+N)
2. Escribir el nombre: feature/modulo-ventas
3. Verificar que dice "From: dev"
4. Clic Create Branch
⌨️ Terminal
# Crear y cambiar a la nueva rama git checkout -b feature/modulo-ventas # Verificar que estamos en la nueva rama git branch # verás * feature/modulo-ventas
3
Trabajar y hacer commits frecuentes
Commits pequeños y descriptivos. No acumules cambios enormes en un solo commit.
🖥️ GitHub Desktop
En el panel de Changes:
1. Marcar los archivos relevantes ✅
2. Escribir Summary: feat(ventas): agregar pantalla de cobro
3. Descripción opcional para más detalle
4. Clic Commit to feature/modulo-ventas
⌨️ Terminal
git add . git commit -m "feat(ventas): agregar pantalla de cobro" # Varios commits durante el desarrollo... git add src/ventas/ git commit -m "feat(ventas): calcular total con IVA" git add . git commit -m "test(ventas): agregar tests de cálculo"
4
Subir la rama a GitHub (push)
Subir los commits al repositorio remoto — la primera vez vincula la rama local con el remoto.
🖥️ GitHub Desktop
Botón Publish branch (primera vez)
o Push origin (los siguientes pushes)

Aparece arriba a la derecha de la ventana.
⌨️ Terminal
# Primera vez — vincula rama local con remoto git push -u origin feature/modulo-ventas # Pushes siguientes (ya vinculada) git push
5
Crear el Pull Request hacia dev
El PR es la propuesta formal de integrar tu trabajo. Incluye descripción clara de qué hiciste y por qué.
🖥️ GitHub Desktop
1. Clic en Create Pull Request (aparece después del push)
2. Abre GitHub Web automáticamente
3. Base: dev ← Compare: feature/modulo-ventas
4. Llenar título y descripción
5. Asignar reviewer
6. Clic Create Pull Request
⌨️ Terminal
# Con GitHub CLI (gh) — crear PR desde terminal gh pr create \ --base dev \ --title "feat(ventas): módulo de cobro completo" \ --body "## Qué incluye\n- Pantalla de cobro\n- Cálculo IVA\n- Tests" \ --reviewer tech-lead # O simplemente abrir en el navegador gh pr create --web
plantilla de Pull Request — VLIMPR TEMPLATE
## ¿Qué hace este PR?
Descripción clara de los cambios implementados.

## Tipo de cambio
- [ ] feat: Nueva funcionalidad
- [ ] fix: Corrección de bug
- [ ] refactor: Refactorización

## ¿Cómo probar?
1. Ejecutar `docker compose up`
2. Ir a /ventas
3. Registrar una venta de prueba

## Checklist
- [ ] Los tests pasan localmente
- [ ] No hay console.log de debug
- [ ] Las variables de entorno necesarias están documentadas
- [ ] El código sigue las convenciones del proyecto

## Screenshots (si aplica)
6
Después del merge: limpiar y actualizar
Una vez aprobado y mergeado el PR, eliminar la rama feature y actualizar dev local.
🖥️ GitHub Desktop
1. Cambiar a rama dev
2. Clic Fetch origin + Pull origin
3. Branch → Delete Branch para eliminar la feature branch

GitHub también te ofrece borrar la rama directamente en el PR mergeado.
⌨️ Terminal
# Volver a dev y actualizar git checkout dev git pull origin dev # Eliminar rama local git branch -d feature/modulo-ventas # Eliminar rama remota (si no se borró al hacer merge) git push origin --delete feature/modulo-ventas

// 06 — CIERRE DE SPRINT

Cierre de Sprint

Al finalizar cada Sprint, el Tech Lead crea un PR de dev → main. Este merge toca producción — se hace con revisión, con --no-ff para preservar el historial, y se etiqueta con un tag de versión. El deploy automático (cap. 09) se dispara solo al detectar el merge en main.

1
Verificar que dev está limpio y todos los PRs del Sprint están mergeados
Antes de hacer el merge a main, confirmar que no hay PRs pendientes de revisión del Sprint actual.
cierre de sprint — proceso completoTECH LEAD
# ── Paso 1: Actualizar ramas locales ──────────────────
git checkout main
git pull origin main

git checkout dev
git pull origin dev

# ── Paso 2: Verificar historial de dev ────────────────
git log --oneline --graph origin/main..origin/dev
# Muestra todos los commits que están en dev pero NO en main
# Revisa que son los commits esperados del Sprint

# ── Paso 3: Opción A — PR en GitHub Web (recomendado) ─
# Crear PR: base main ← compare dev
# Asignar al menos 1 reviewer
# Revisar los cambios en la pestaña Files changed
# Aprobar y hacer merge con "Create a merge commit" (--no-ff)

# ── Paso 3: Opción B — merge por consola ──────────────
git checkout main
git merge --no-ff dev -m "merge: Sprint 5 → main"
# --no-ff = "No Fast Forward" — crea un commit de merge visible
# El historial queda claro: se ve exactamente cuándo cerró cada Sprint

# ── Paso 4: Crear tag de versión ──────────────────────
git tag -a v1.5.0 -m "Sprint 5 — módulo de ventas + reportes"
git push origin main
git push origin v1.5.0  # los tags NO se pushean automáticamente

# ── Paso 5: Sincronizar dev con main ──────────────────
# Importante: dev debe arrancar el siguiente Sprint desde main
git checkout dev
git merge main            # fast-forward, no hay diferencias
git push origin dev

# ── Verificar resultado ───────────────────────────────
git log --oneline --graph --all -10
# Deberías ver:
# *   a3f2bc1 (HEAD -> main, tag: v1.5.0) merge: Sprint 5 → main
# |\
# | * 9d1e4f2 feat(ventas): pantalla de cobro
# | * 7c2a1b3 fix(auth): expiración de sesión
# |/
# * 5b8d9e1 (tag: v1.4.0) merge: Sprint 4 → main
⚠️
Por qué --no-ff y no squash mergeCon --no-ff el historial muestra claramente cada merge de Sprint — puedes ver cuándo llegó cada feature a producción. Con squash se pierde el historial detallado. Para el cierre de Sprint a main, siempre --no-ff (merge commit). Para features dentro del Sprint, squash en el PR está bien si prefieres un historial más limpio en dev.
Estrategia de mergeCuándo usarla en VLIMResultado en historial
Merge commit (--no-ff)feature → dev y dev → main (Sprints)Historial completo, merge commit visible
Squash and mergeOpcional para feature → dev (historial limpio)N commits → 1 commit en dev
Rebase and mergeNo recomendado en ramas compartidasHistorial lineal pero reescribe commits

// 07 — PROTEGER RAMAS

Proteger Ramas

Branch Protection Rules en GitHub hacen que las reglas sean imposibles de saltarse accidentalmente — incluso para el owner del repositorio. Es la forma de garantizar que nadie rompa producción con un push directo.

GitHub → Settings → Branches → Branch Protection RulesGITHUB WEB
── Configuración recomendada para main ─────────────────────────────

Branch name pattern: main

✅ Require a pull request before merging
   └─ Require approvals: 1  (al menos 1 aprobación del Tech Lead)
   └─ Dismiss stale pull request approvals when new commits are pushed
      (si el dev sube más commits después de la aprobación, re-requiere review)

✅ Require status checks to pass before merging
   └─ Require branches to be up to date before merging
   └─ Status checks: "test" y "build" (de GitHub Actions, cap. 08)

✅ Require conversation resolution before merging
   └─ Todos los comentarios del PR deben resolverse antes de mergear

✅ Require linear history   (opcional — commits limpios)

✅ Do not allow bypassing the above settings
   └─ Ni admins pueden saltarse las reglas

── Configuración recomendada para dev ──────────────────────────────

Branch name pattern: dev

✅ Require a pull request before merging
   └─ Require approvals: 1  (peer review del equipo)

✅ Require status checks to pass
   └─ "test" debe pasar (CI corre los tests automáticamente)

── Regla adicional — bloquear push directo a cualquier feature ─────
   (opcional, más restrictivo)
Branch name pattern: main  y  dev
✅ Block force pushes
✅ Block deletions
🔒
Resultado de activar estas reglas en VLIMUn desarrollador intenta hacer git push origin main directamente → GitHub rechaza con error "protected branch hook declined". La única manera de integrar código es por PR aprobado. Los tests de CI deben pasar. Esto hace que sea prácticamente imposible romper producción por accidente.

// 08 — GITHUB ACTIONS

GitHub Actions

GitHub Actions es el CI/CD nativo de GitHub — sin costo adicional para repos privados hasta 2000 min/mes. Los workflows se definen en YAML en el repo, corren en máquinas virtuales de GitHub y se disparan con eventos del repositorio (push, PR, merge, tag).

CI en cada PR
Tests automáticos al abrir o actualizar un PR hacia dev.
🚀
Deploy en merge a main
Deploy automático a producción al cerrar el Sprint.
🐳
Build Docker
Construir y publicar imagen al registry en cada merge a main.
🏷️
Release automático
Crear GitHub Release y changelog al pushear un tag v*.
.github/workflows/ci.yml — CI en cada PR hacia devCI
name: CI — Tests y Build

on:
  pull_request:
    branches: [dev, main]   # corre en todo PR hacia dev o main
  push:
    branches: [dev]           # también al mergear a dev

jobs:
  test:
    name: Tests
    runs-on: ubuntu-latest

    services:                  # contenedores disponibles durante el job
      postgres:
        image: postgres:16-alpine
        env:
          POSTGRES_DB:       erp_test
          POSTGRES_USER:     test_user
          POSTGRES_PASSWORD: test_pass
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

      redis:
        image: redis:7-alpine
        options: --health-cmd "redis-cli ping" --health-interval 5s

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js 20
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'            # cachea node_modules entre runs

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Type check
        run: npm run typecheck

      - name: Run tests
        run: npm test
        env:
          NODE_ENV:     test
          DB_HOST:      localhost
          DB_PORT:      5432
          DB_NAME:      erp_test
          DB_USER:      test_user
          DB_PASSWORD:  test_pass
          REDIS_HOST:   localhost

  build:
    name: Build Docker image
    runs-on: ubuntu-latest
    needs: test                # solo si los tests pasan
    steps:
      - uses: actions/checkout@v4
      - name: Build Docker image (verificar que compila)
        run: docker build --target production -t erp-api:ci-test .

// 09 — DEPLOY AUTOMÁTICO

Deploy Automático

El deploy a producción se dispara automáticamente cuando un PR se mergea a main — es decir, al cierre de cada Sprint. El workflow construye la imagen Docker, la publica al registry y despliega en el servidor via SSH, todo sin intervención manual.

💡
¿Por qué GitHub Actions y no otros?GitHub Actions es la mejor opción para VLIM porque: ya están en GitHub (sin cuenta extra), los minutos gratuitos son suficientes para el Sprint, los secrets se manejan directamente en el repo, y la integración con PR + Branch Protection es nativa. Alternativas: Render (deploy automático sin config), Railway (muy sencillo), o un VPS con webhook propio si quieren más control.
.github/workflows/deploy.yml — deploy al cerrar Sprint (merge a main)DEPLOY
name: Deploy a Producción — Cierre de Sprint

on:
  push:
    branches: [main]    # se dispara cuando llega un merge a main
  workflow_dispatch:      # también permite correrlo manualmente desde GitHub

env:
  REGISTRY:  ghcr.io
  IMAGE:     ghcr.io/${{ github.repository_owner }}/erp-api

jobs:
  # ── Job 1: Build y push de imagen Docker ────────────
  build-and-push:
    name: Build y Push imagen
    runs-on: ubuntu-latest
    outputs:
      image-tag: ${{ steps.meta.outputs.version }}

    steps:
      - uses: actions/checkout@v4

      - name: Setup BuildKit
        uses: docker/setup-buildx-action@v3

      - name: Login al GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}   # automático, no requiere config

      - name: Extraer metadatos (tag automático)
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.IMAGE }}
          tags: |
            type=sha,prefix=sha-          # sha-a1b2c3d
            type=raw,value=latest         # latest siempre apunta a main
            type=semver,pattern={{version}}  # si hay tag v1.5.0

      - name: Build y Push
        uses: docker/build-push-action@v5
        with:
          context: .
          target:  production
          push:    true
          tags:    ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to:   type=gha,mode=max

  # ── Job 2: Deploy en el servidor ────────────────────
  deploy:
    name: Deploy a servidor
    runs-on: ubuntu-latest
    needs: build-and-push    # espera a que la imagen esté publicada
    environment: production  # entorno con aprobación manual opcional

    steps:
      - name: Deploy via SSH
        uses: appleboy/[email protected]
        with:
          host:     ${{ secrets.DEPLOY_HOST }}     # IP del servidor
          username: ${{ secrets.DEPLOY_USER }}     # usuario SSH
          key:      ${{ secrets.DEPLOY_SSH_KEY }}  # llave privada SSH
          script: |
            cd /opt/erp
            echo "${{ secrets.GITHUB_TOKEN }}" | \
              docker login ghcr.io -u ${{ github.actor }} --password-stdin
            docker compose pull api worker
            docker compose up -d --no-deps api worker
            docker compose exec -T api node dist/migrate.js   # migraciones
            docker image prune -f
            echo "✅ Deploy Sprint completado: $(date)"

      - name: Notificar Slack (opcional)
        if: always()
        uses: rtCamp/action-slack-notify@v2
        env:
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
          SLACK_MESSAGE: >
            ${{ job.status == 'success' && '✅ Deploy exitoso' || '❌ Deploy falló' }}
            — Sprint mergeado a main
secrets requeridos — configurar en GitHub Settings → SecretsCONFIG
# Ir a: Repo → Settings → Secrets and variables → Actions → New repository secret

DEPLOY_HOST       # IP o dominio del servidor: "192.168.1.100"
DEPLOY_USER       # Usuario SSH: "ubuntu" o "deploy"
DEPLOY_SSH_KEY    # Llave privada SSH (contenido de ~/.ssh/id_ed25519)
SLACK_WEBHOOK     # URL de webhook de Slack (opcional)

# GITHUB_TOKEN es automático — GitHub lo genera por job, no requiere config

# Generar llave SSH dedicada para el deploy (no usar tu llave personal)
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/deploy_key -N ""
# Copiar la llave pública al servidor:
cat ~/.ssh/deploy_key.pub >> ~/.ssh/authorized_keys   # en el servidor
# Copiar la llave PRIVADA a GitHub Secrets como DEPLOY_SSH_KEY:
cat ~/.ssh/deploy_key
Demo — simulación del pipeline completo VLIM: PR → CI → merge → deploy▶ LIVE
// Simular el flujo completo VLIM async function sleep(ms) { return new Promise(r => setTimeout(r, ms)); } const sprint = { numero: 5, features: [ { rama: 'feature/modulo-ventas', dev: 'Ana', commits: 4 }, { rama: 'feature/reportes-diarios',dev: 'Bob', commits: 3 }, { rama: 'fix/stock-negativo', dev: 'Carlos', commits: 1 }, ] }; async function runCI(rama) { await sleep(200 + Math.random() * 300); const ok = Math.random() > 0.1; // 90% pasan if (!ok) throw new Error(`Tests fallaron en ${rama}`); return true; } async function mergePR(feature) { console.log(`\n📋 PR: ${feature.rama} → dev`); console.log(` Autor: ${feature.dev} (${feature.commits} commits)`); console.log(` ⚙️ CI: corriendo tests...`); await runCI(feature.rama); console.log(` ✅ CI pasó — 1 aprobación del Tech Lead`); await sleep(150); console.log(` 🔀 Mergeado a dev (merge commit --no-ff)`); } // Sprint: todos los PRs a dev console.log(`🏃 Sprint ${sprint.numero} — ${sprint.features.length} features`); console.log('='.repeat(44)); for (const f of sprint.features) { await mergePR(f); } // Cierre de Sprint: dev → main console.log('\n' + '='.repeat(44)); console.log('🚀 CIERRE DE SPRINT — PR: dev → main'); console.log(' Reviewers: Tech Lead ✅'); await sleep(300); console.log(' ✅ CI completo (tests + build Docker)'); await sleep(200); console.log(' 🔀 Merge a main (--no-ff)'); console.log(` 🏷️ Tag creado: v1.${sprint.numero}.0`); await sleep(300); // Deploy automático console.log('\n⚡ GitHub Actions: Deploy automático'); console.log(' 🐳 docker build --target production'); await sleep(400); console.log(' 📤 docker push ghcr.io/vlim/erp-api:latest'); await sleep(300); console.log(' 🌐 SSH → docker compose pull + up -d'); await sleep(300); console.log(' 🗄️ node dist/migrate.js (migraciones)'); await sleep(200); console.log(`\n✅ Sprint ${sprint.numero} en producción 🎉`);
// outputHaz clic en Ejecutar...

// 10 — CONFLICTOS Y RESOLUCIÓN

Conflictos y Resolución

Un conflicto ocurre cuando dos ramas modificaron la misma línea del mismo archivo. Git no sabe cuál versión conservar — tienes que decidirlo tú. No son un error, son parte normal del trabajo en equipo.

qué parece un conflicto y cómo resolverloCONFLICTOS
# Git marca los conflictos así en el archivo:
<<<<<<< HEAD (dev — tu rama actual)
const precio = calcularConIVA(base);
=======
const precio = calcularConDescuento(base, descuento);
>>>>>>> feature/descuentos (la rama entrante)

# Tu decisión: eliminar los marcadores y dejar el código correcto
# Opción A — conservar solo HEAD (lo tuyo)
const precio = calcularConIVA(base);

# Opción B — conservar solo la rama entrante
const precio = calcularConDescuento(base, descuento);

# Opción C — combinar ambos cambios (la más común)
const precio = calcularConIVA(calcularConDescuento(base, descuento));
🖥️ GitHub Desktop
Si hay conflictos al mergear, Desktop muestra una pantalla con los archivos en conflicto.

1. Clic en Open in Visual Studio Code (o el editor configurado)
2. VS Code muestra los conflictos con botones: Accept Current Change / Accept Incoming Change / Accept Both
3. Elegir la opción correcta en cada conflicto
4. Guardar el archivo
5. Volver a Desktop → los archivos resueltos se marcan ✅
6. Clic en Continue Merge
⌨️ Terminal
# Actualizar tu feature con los últimos cambios de dev git checkout feature/mi-tarea git merge dev # puede generar conflictos # Ver qué archivos tienen conflictos git status # muestra "both modified" # Abrir en VS Code para resolver code . # Después de resolver TODOS los conflictos git add . git commit -m "merge: integrar cambios de dev" # Si prefieres abortar y empezar de nuevo git merge --abort
🛡️
Cómo minimizar conflictos en VLIM 1. Hace pull de dev todos los días antes de empezar a trabajar.
2. Ramas cortas — no tengas una feature branch abierta por 2 semanas.
3. Divide el trabajo para que distintos devs toquen distintos archivos.
4. Comunica en el equipo cuando vas a hacer cambios en archivos compartidos (config, tipos globales, etc.).

// 11 — BUENAS PRÁCTICAS

Buenas Prácticas

Las buenas prácticas de Git no son burocracia — son las que hacen que el historial sea útil cuando algo falla en producción a las 2am. Con ellas puedes saber en 30 segundos qué cambió, cuándo y quién.

PrácticaPor quéEn VLIM
Commits pequeños y frecuentes Más fácil revisar, revertir y encontrar bugs con git bisect Al menos 1 commit por sub-tarea lógica
Conventional Commits Historial legible, changelogs automáticos, semver automático feat/fix/refactor/docs/chore obligatorio
Ramas de vida corta Menos conflictos, más integración continua real Max 5-7 días, idealmente 1-2 días
Nunca --force en ramas compartidas Reescribir historial rompe el repo de otros --force solo permitido en tu feature branch personal
.gitignore completo Evitar subir node_modules, .env, archivos de build Usar plantilla de Node.js + ajustes del proyecto
Nunca secrets en el repo GitHub indexa todos los commits — los secrets quedan expuestos para siempre Variables en GitHub Secrets + .env.example en repo
.gitignore — plantilla para el ERP VLIM (Node.js)CONFIG
# Dependencias
node_modules/
.pnp
.pnp.js

# Build
dist/
build/
*.tsbuildinfo

# Entorno — NUNCA al repositorio
.env
.env.*
!.env.example    # .env.example SÍ va al repo (template sin valores reales)

# Logs
*.log
logs/
npm-debug.log*

# Cobertura de tests
coverage/
.nyc_output/

# Sistema operativo
.DS_Store
Thumbs.db
*.swp

# Docker
docker-compose.override.yml   # config local de cada dev

# IDEs
.vscode/settings.json         # settings personales (NO extensiones recomendadas)
.idea/
*.suo

# Uploads locales en desarrollo
uploads/
tmp/

// 12 — COMANDOS DE EMERGENCIA

Comandos de Emergencia

Errores que cometen todos en algún momento — y cómo salir de ellos. La mayoría son reversibles si actúas rápido antes de hacer push.

situaciones de emergencia y sus solucionesEMERGENCIAS
# ── "Hice commit en la rama equivocada" ───────────────
# Ejemplo: commiteé en dev en vez de en mi feature branch
git log --oneline -3               # obtener el SHA del commit accidental
git checkout feature/mi-tarea     # ir a la rama correcta
git cherry-pick <SHA>              # aplicar el commit aquí
git checkout dev
git reset --soft HEAD~1             # deshacer el commit en dev (guarda los cambios)
git stash                          # guardar temporalmente los cambios

# ── "Necesito deshacer el último commit (sin publicar)" ─
git reset --soft HEAD~1            # deshace el commit, guarda los cambios en staging
git reset        HEAD~1            # deshace commit y staging, guarda en working tree
git reset --hard HEAD~1            # ⚠️ deshace todo, PIERDE los cambios del commit

# ── "Subí algo que no debía (ya hice push)" ───────────
# NUNCA uses --force en dev o main. Usa revert:
git revert <SHA>                   # crea un nuevo commit que deshace el anterior
git push origin feature/mi-tarea  # seguro, no reescribe historial

# ── "Borrré un archivo sin querer" ────────────────────
git checkout HEAD -- archivo.ts    # restaurar desde el último commit
git restore archivo.ts             # alternativa moderna

# ── "Necesito pausar mi trabajo para revisar un bug urgente" ──
git stash                          # guardar cambios sin commitear
git stash push -m "WIP: pantalla de cobro"  # con nombre descriptivo
# ... resolver el bug en otra rama ...
git stash pop                      # recuperar los cambios guardados
git stash list                     # ver stashes guardados

# ── "Qué cambió exactamente en este commit" ───────────
git show <SHA>                     # ver diff completo del commit
git show <SHA> --stat             # solo qué archivos cambiaron
git blame archivo.ts               # quién modificó cada línea
git log -S "calcularIVA"          # buscar commits que tocaron esta función

# ── "El PR en GitHub dice que hay conflictos" ─────────
git checkout feature/mi-tarea
git fetch origin
git merge origin/dev             # traer los últimos cambios de dev
# resolver conflictos (ver cap. 10)
git push                          # el PR se actualiza automáticamente

# ── "Hice git reset --hard y perdí commits" ───────────
git reflog                         # historial de TODO lo que HEAD apuntó
git checkout <SHA-del-reflog>     # recuperar desde el reflog (tienes ~30 días)
🚨
Comandos que NUNCA usar en ramas compartidas (dev, main)git push --force o git push -f, git reset --hard después de push, git rebase en commits ya publicados. Estos reescriben el historial — el repo de todos los demás quedará inconsistente y tendrán que hacer reset a mano. En tu feature branch personal (no publicada) sí puedes usarlos.

// 13 — REFERENCIA RÁPIDA

Referencia Rápida

Todos los comandos del día a día ordenados por categoría. Imprímela o tenla a mano durante las primeras semanas.

cheatsheet — comandos esenciales VLIMCHEATSHEET
# ── Inicio del día ─────────────────────────────────────
git checkout dev && git pull origin dev        # actualizar dev
git checkout feature/mi-tarea                # cambiar a mi rama
git merge dev                                 # traer últimos cambios de dev a mi rama

# ── Trabajo diario ─────────────────────────────────────
git status                                    # ver qué cambió
git diff                                      # ver cambios línea a línea
git add .                                     # agregar todo al staging
git add <archivo>                             # agregar archivo específico
git commit -m "feat(scope): descripción"    # commit con mensaje
git push                                      # subir a GitHub

# ── Ramas ──────────────────────────────────────────────
git branch                                    # listar ramas locales
git checkout -b feature/nombre              # crear y cambiar a nueva rama
git checkout dev                             # cambiar a dev
git branch -d feature/nombre               # borrar rama local (después del merge)
git push origin --delete feature/nombre    # borrar rama remota

# ── Historial ──────────────────────────────────────────
git log --oneline                            # historial compacto
git log --oneline --graph --all             # historial con árbol de ramas
git show <SHA>                               # ver un commit específico
git log --author="Ana" --since="1 week ago"# filtrar por autor y fecha

# ── Cierre de Sprint (Tech Lead) ───────────────────────
git checkout main && git pull origin main
git checkout dev  && git pull origin dev
git checkout main
git merge --no-ff dev -m "merge: Sprint N → main"
git tag -a vX.Y.Z -m "Sprint N completado"
git push origin main && git push origin vX.Y.Z
git checkout dev && git merge main && git push origin dev

# ── GitHub CLI (instalación opcional) ─────────────────
# brew install gh  /  winget install GitHub.cli
gh pr create --web                           # crear PR desde terminal
gh pr list                                    # ver PRs abiertos
gh pr checkout 42                             # bajar el PR #42 localmente
gh workflow run deploy.yml                   # triggear workflow manualmente
gh run list                                   # ver últimos runs de Actions
Resumen del flujo VLIM en 6 líneas
1. git pull origin dev → actualizar antes de empezar
2. git checkout -b feature/nombre → crear rama desde dev
3. Trabajar → git add . && git commit -m "feat: ..."
4. git push -u origin feature/nombre → subir a GitHub
5. Crear PR en GitHub Web: feature → dev, pedir review
6. Al cierre del Sprint: Tech Lead hace PR dev → main → deploy automático 🚀