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 mainReglas:
mainsiempre esta en estado deployable- Crear una rama descriptiva para cada tarea
- Hacer PR con code review antes de mergear
- 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)
|-- commitRequiere: 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~4Esto 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 commitResultado 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 listAhora 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 resetAutomatizar 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-loginVentajas:
- 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 initPre-commit: verificar antes de cada commit
# .husky/pre-commit
npx lint-stagedCon 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 $1Con 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.tsAlias ú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-statusChecklist 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
maincontra 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.



Comentarios (0)
Inicia sesión para comentar