Git: más alla de add, commit y push

La mayoria de los desarrolladores usan Git a un nivel básico: add, commit, push, pull. Pero Git es una herramienta extraordinariamente poderosa que, bien utilizada, puede transformar la productividad de un equipo. En este articulo exploramos técnicas avanzadas y flujos de trabajo profesionales.

Estrategias de branching

GitHub Flow (recomendado para la mayoria)

El flujo más simple y efectivo para la mayoria de equipos:

main (siempre deployable)
  |
  +-- feat/nueva-funcionalidad
  |     |-- commit 1
  |     |-- commit 2
  |     +-- PR -> merge a main
  |
  +-- fix/corregir-bug
        |-- commit 1
        +-- PR -> merge a main

Reglas:

  1. main siempre esta en estado deployable
  2. Crear una rama descriptiva para cada tarea
  3. Hacer PR con code review antes de mergear
  4. Deployar inmediatamente despues del merge

GitFlow (para releases planificados)

Para proyectos con ciclos de release definidos:

main (producción)
  |
develop (integración)
  |
  +-- feature/login
  +-- feature/dashboard
  |
release/1.2.0 (preparacion)
  |
hotfix/critical-bug (urgencias en producción)

Trunk-Based Development (para CI/CD maduros)

Todos trabajan directamente en main con feature flags:

main
  |-- commit (con feature flag)
  |-- commit (con feature flag)
  |-- commit

Requiere: CI/CD robusto, feature flags, testing automatizado fuerte.

Commits atomicos y convencionales

Conventional Commits

Una convención de mensajes que facilita la generación automática de changelogs:

<tipo>(<scope>): <descripción>

[cuerpo opcional]

[footer opcional]

Tipos estandar:

Tipo Uso
feat Nueva funcionalidad
fix Correccion de bug
docs Cambios en documentación
style Formato (sin cambio de lógica)
refactor Reestructuracion sin cambio funcional
perf Mejora de rendimiento
test Agregar o modificar tests
chore Tareas de mantenimiento
ci Cambios en CI/CD

Ejemplos reales:

git commit -m "feat(auth): add Google OAuth login flow"
git commit -m "fix(search): resolve empty results on special characters"
git commit -m "refactor(courses): migrate to signal-based state"
git commit -m "perf(images): implement lazy loading for course thumbnails"

Commits atomicos

Cada commit debe representar un solo cambio lógico que se puede revertir independientemente:

# MAL: un commit gigante
git commit -m "add login, fix navbar, update styles, refactor services"

# BIEN: commits atomicos
git commit -m "feat(auth): add login component with form validation"
git commit -m "fix(navbar): correct sticky positioning on scroll"
git commit -m "style(global): update color variables for dark mode"
git commit -m "refactor(services): extract HTTP logic to base service"

Rebase interactivo

El rebase interactivo te permite reescribir el historial de commits antes de mergear.

Limpiar historial antes de un PR

# Rebase interactivo de los ultimos 4 commits
git rebase -i HEAD~4

Esto abre un editor con las opciones:

pick abc1234 feat(search): add search input component
pick def5678 WIP: search logic
pick ghi9012 fix typo in search
pick jkl3456 feat(search): add results list

# Comandos disponibles:
# p, pick   = usar commit tal cual
# r, reword = usar commit pero editar mensaje
# e, edit   = usar commit pero pausar para editar
# s, squash = combinar con el commit anterior
# f, fixup  = como squash pero descarta el mensaje
# d, drop   = eliminar commit

Resultado limpio:

pick abc1234 feat(search): add search input component
fixup def5678 WIP: search logic
fixup ghi9012 fix typo in search
pick jkl3456 feat(search): add results list

Ahora tienes 2 commits limpios en lugar de 4 desordenados.

Rebase vs Merge

Aspecto Rebase Merge
Historial Lineal, limpio Con merge commits
Conflictos Se resuelven commit por commit Se resuelven una vez
Seguridad Reescribe historial No reescribe nada
Recomendado Ramas locales, antes de PR Ramas compartidas, PRs

Regla de oro: Nunca hagas rebase de ramas que ya estan publicadas y compartidas.

Git Bisect: encontrar el commit que rompio algo

git bisect usa busqueda binaria para encontrar el commit exacto que introdujo un bug:

# Iniciar bisect
git bisect start

# Marcar el estado actual como malo
git bisect bad

# Marcar un commit anterior donde funcionaba
git bisect good v1.0.0

# Git hace checkout de un commit intermedio
# Prueba si el bug existe y marca:
git bisect good  # si funciona
git bisect bad   # si tiene el bug

# Git sigue dividiendo hasta encontrar el commit exacto
# Resultado: "abc1234 is the first bad commit"

# Terminar bisect
git bisect reset

Automatizar bisect con un script

# Ejecutar automaticamente un test para cada commit
git bisect start HEAD v1.0.0
git bisect run npm test -- --filter "search.spec"

Git ejecuta el test en cada commit y marca automaticamente good/bad segun el exit code.

Git Worktrees: multiples ramas simultaneas

Los worktrees permiten tener multiples ramas checked out al mismo tiempo en directorios separados:

# Crear un worktree para un hotfix sin perder tu trabajo actual
git worktree add ../hotfix-login fix/login-crash

# Trabajar en el hotfix
cd ../hotfix-login
# ... hacer cambios, commit, push ...

# Volver y eliminar el worktree
cd ../proyecto-principal
git worktree remove ../hotfix-login

Ventajas:

  • No necesitas stash ni commit temporal
  • Puedes trabajar en dos features simultaneamente
  • Ideal para revisiones de código mientras trabajas en otra cosa

Git Hooks con Husky

Los hooks ejecutan scripts automaticamente en eventos de Git:

# Instalar husky
npm install -D husky
npx husky init

Pre-commit: verificar antes de cada commit

# .husky/pre-commit
npx lint-staged

Con lint-staged en package.json:

{
  "lint-staged": {
    "*.ts": ["eslint --fix", "prettier --write"],
    "*.css": ["prettier --write"],
    "*.html": ["prettier --write"]
  }
}

Commit-msg: validar el formato del mensaje

# .husky/commit-msg
npx commitlint --edit $1

Con la configuración de commitlint:

// commitlint.config.js
export default {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'scope-enum': [2, 'always', [
      'auth', 'blog', 'courses', 'search', 'ui', 'core'
    ]],
  },
};

Git Stash avanzado

Stash con nombre

# Guardar con mensaje descriptivo
git stash push -m "WIP: search dialog keyboard navigation"

# Ver stashes guardados
git stash list
# stash@{0}: On feat/search: WIP: search dialog keyboard navigation

# Aplicar un stash específico sin eliminarlo
git stash apply stash@{0}

# Aplicar y eliminar
git stash pop stash@{0}

Stash parcial

# Stash solo archivos específicos
git stash push -m "solo estilos" src/styles.css src/app/**/*.css

# Stash interactivo: elegir hunks
git stash push -p -m "cambios parciales"

Git Log avanzado

Visualizar historial de forma clara

# Grafo de commits con colores
git log --oneline --graph --all --decorate

# Buscar commits por mensaje
git log --grep="search" --oneline

# Commits de un autor en un rango de fechas
git log --author="David" --after="2025-01-01" --before="2026-01-01" --oneline

# Archivos cambiados en cada commit
git log --stat --oneline -10

# Cambios en un archivo específico
git log --follow -p -- src/app/core/services/search.service.ts

Alias útiles para tu .gitconfig

[alias]
  lg = log --oneline --graph --all --decorate -20
  st = status -sb
  co = checkout
  br = branch -v
  unstage = reset HEAD --
  last = log -1 HEAD --stat
  contributors = shortlog -sn --all
  changed = diff --name-status

Checklist para equipos

  • Definir y documentar la estrategia de branching
  • Usar Conventional Commits con commitlint
  • Configurar pre-commit hooks con lint-staged
  • Exigir PRs con al menos un reviewer
  • Mantener PRs pequenos y enfocados (menos de 400 lineas)
  • Hacer squash merge o rebase antes de mergear
  • Proteger la rama main contra push directo
  • Automatizar CI en cada PR (lint, test, build)

Conclusion

Git es mucho más que un sistema de control de versiones: es una herramienta de colaboracion que, bien configurada, puede eliminar fricciones significativas en el flujo de trabajo de un equipo. Invierte tiempo en aprender rebase interactivo, bisect y worktrees. Configura hooks y convenciones de commits. Tu yo del futuro (y tu equipo) te lo agradeceran.