Tech Tips Monday: 7 Técnicas Avanzadas de Git que Transformarán tu Flujo de Trabajo
Comenzamos una nueva semana con Tech Tips Monday. Hoy el enfoque está en los flujos de trabajo avanzados de Git: técnicas que van más allá de commit y push, optimizando la colaboración, el depuración y el mantenimiento de un historial limpio.
1. Rebase Interactivo para un Historial Limpio
El rebase interactivo permite reescribir el historial antes de hacer push, creando commits organizados y significativos.
Reorganizar Commits:
# Rebase interactivo de los últimos 5 commits
git rebase -i HEAD~5
# En el editor verás:
# pick a1b2c3d feat: add user authentication
# pick d4e5f6g fix: typo in validation
# pick h7i8j9k feat: add password reset
# pick k0l1m2n wip: debugging session
# pick n3o4p5q fix: authentication edge case
Comandos Disponibles:
# pick (p) - usar commit tal cual
# reword (r) - cambiar mensaje de commit
# edit (e) - pausar para modificar commit
# squash (s) - combinar con commit anterior
# fixup (f) - combinar sin mensaje
# drop (d) - eliminar commit
# exec (x) - ejecutar comando shell
# Ejemplo de reorganización:
pick a1b2c3d feat: add user authentication
fixup n3o4p5q fix: authentication edge case
reword d4e5f6g fix: typo in validation
squash h7i8j9k feat: add password reset
drop k0l1m2n wip: debugging session
Autosquash Workflow:
# Durante desarrollo, marca commits para squash automático
git commit -m "feat: add feature X"
git commit -m "fixup! feat: add feature X" # Se auto-squash
git commit -m "squash! feat: add feature X" # Se auto-squash con mensaje
# Al hacer rebase, se organizan automáticamente
git rebase -i --autosquash main
Configuración Recomendada:
# Habilitar autosquash por defecto
git config --global rebase.autosquash true
# Habilitar auto-stash antes de rebase
git config --global rebase.autoStash true
2. Git Worktrees para Múltiples Branches Simultáneos
Trabaja en múltiples branches sin cambiar de contexto o hacer stash constante.
Setup Básico:
# Crear worktree adicional
git worktree add ../mi-proyecto-feature-x feature-x
git worktree add ../mi-proyecto-hotfix hotfix/critical-bug
# Ahora tienes directorios separados:
# ~/Projects/mi-proyecto/ (main branch)
# ~/Projects/mi-proyecto-feature-x/ (feature-x branch)
# ~/Projects/mi-proyecto-hotfix/ (hotfix branch)
# Listar worktrees activos
git worktree list
Workflow Práctico:
# Terminal 1: Development en feature
cd ~/Projects/mi-proyecto-feature-x
npm run dev
# Terminal 2: Hotfix urgente
cd ~/Projects/mi-proyecto-hotfix
npm run test
git commit -m "fix: critical security issue"
git push
# Terminal 3: Code review
cd ~/Projects/mi-proyecto
git worktree add ../review-pr-123 pr-123
cd ../review-pr-123
npm install
npm test
Cleanup:
# Remover worktree cuando termines
git worktree remove ../mi-proyecto-feature-x
# Forzar remoción si hay cambios sin commit
git worktree remove --force ../mi-proyecto-hotfix
# Limpiar referencias huérfanas
git worktree prune
Ventajas:
- Múltiples branches ejecutándose simultáneamente
- Sin perder contexto de desarrollo
- Ideal para code reviews sin interrumpir trabajo actual
- Testing paralelo en diferentes branches
3. Git Bisect para Debugging de Regresiones
Encuentra automáticamente el commit que introdujo un bug usando búsqueda binaria.
Uso Básico:
# Iniciar bisect
git bisect start
# Marcar commit actual como malo
git bisect bad
# Marcar último commit conocido bueno (ej: tag anterior)
git bisect good v1.2.0
# Git hace checkout automático del punto medio
# Probar si el bug existe
npm test
# Si tests pasan:
git bisect good
# Si tests fallan:
git bisect bad
# Repetir hasta encontrar el commit culpable
# Git mostrará: "X is the first bad commit"
Bisect Automatizado:
# Automatizar con script de test
git bisect start HEAD v1.2.0
git bisect run npm test
# O con comando personalizado
git bisect run ./scripts/check-regression.sh
# Script check-regression.sh:
#!/bin/bash
npm test
exit $? # 0 = good, 1 = bad
Bisect con Términos Personalizados:
# Usar términos más descriptivos que good/bad
git bisect start --term-new=broken --term-old=working
git bisect broken # en lugar de 'bad'
git bisect working # en lugar de 'good'
Skip Commits:
# Si un commit no compila o no se puede probar
git bisect skip
# Skip rango de commits
git bisect skip v1.0..v1.1
Finalizar Bisect:
# Una vez identificado el problema
git bisect reset # Vuelve a branch original
# Ver log de bisect
git bisect log
# Replay de sesión anterior
git bisect replay bisect.log
4. Git Reflog: El Salvavidas para Errores
Reflog registra todos los cambios a HEAD, permitiendo recuperar commits “perdidos”.
Casos de Uso Comunes:
# Ver historial completo de HEAD
git reflog
# Output:
# a1b2c3d HEAD@{0}: commit: feat: add feature
# d4e5f6g HEAD@{1}: rebase -i: squash commits
# h7i8j9k HEAD@{2}: reset: moving to HEAD~1
# k0l1m2n HEAD@{3}: commit: wip: debugging
# Recuperar commit después de reset accidental
git reset --hard HEAD@{3}
# Recuperar branch eliminado accidentalmente
git checkout -b recovered-branch HEAD@{5}
Buscar en Reflog:
# Buscar commits por mensaje
git reflog | grep "feat: important feature"
# Ver reflog de branch específico
git reflog show feature-branch
# Reflog con fechas legibles
git reflog --date=relative
# Reflog con más detalles
git reflog show --all
Recuperación de Scenarios Comunes:
# Escenario 1: Rebase que salió mal
git reflog
git reset --hard HEAD@{before-rebase}
# Escenario 2: Branch eliminado accidentalmente
git reflog | grep "branch-name"
git checkout -b branch-name```html
<commit-hash>
# Escenario 3: Commit perdido después de reset
git reflog
git cherry-pick <commit-hash>
# Escenario 4: Merge mal hecho
git reflog
git reset --hard HEAD@{before-merge}
Configuración de Retención:
# Cambiar tiempo de retención de reflog (default 90 días)
git config --global gc.reflogExpire 180.days
git config --global gc.reflogExpireUnreachable 90.days
5. Git Stash Avanzado para Contexto Switching
Gestiona cambios work-in-progress de manera organizada.
Stash con Nombres Descriptivos:
# Stash básico con mensaje
git stash push -m "WIP: user authentication feature"
# Stash archivos específicos
git stash push -m "API changes only" api/users.ts api/auth.ts
# Stash incluyendo untracked files
git stash push -u -m "Including new config files"
# Stash todo incluyendo ignored files
git stash push -a -m "Complete workspace state"
Gestión de Stashes:
# Listar stashes con detalles
git stash list
# stash@{0}: On main: WIP: user authentication
# stash@{1}: On feature-x: API changes only
# stash@{2}: On main: Including new config files
# Ver contenido de stash sin aplicar
git stash show stash@{0}
git stash show -p stash@{0} # Con diff completo
# Aplicar stash específico sin removerlo
git stash apply stash@{1}
# Aplicar y remover stash
git stash pop stash@{0}
# Crear branch desde stash
git stash branch new-feature-branch stash@{2}
Stash Parcial (Patch Mode):
# Stash interactivo - elige qué cambios guardar
git stash push -p
# Git preguntará por cada hunk:
# y - stash este hunk
# n - no stash este hunk
# q - quit; no stash este ni los restantes
# a - stash este y todos los restantes
# d - no stash este ni los restantes
# s - split hunk en partes más pequeñas
# e - edit hunk manualmente
Stash Workflow Patterns:
# Pattern 1: Quick context switch
alias gswitch='git stash push -u -m "Quick switch: $(git branch --show-current)"'
# Pattern 2: Stash untracked only
alias gstash-new='git stash push -u --keep-index -m "New files only"'
# Pattern 3: Stash por tipo de cambio
git stash push tests/**/*.test.ts -m "Test changes only"
git stash push src/**/*.css -m "Style changes only"
Limpieza de Stashes:
# Eliminar stash específico
git stash drop stash@{1}
# Eliminar todos los stashes
git stash clear
# Crear backup antes de limpiar
git stash list > stash-backup.txt
6. Git Aliases Productivos
Crea comandos personalizados que simplifiquen workflows complejos.
Aliases de Navegación:
# Ver commits recientes con formato bonito
git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative"
# Uso: git lg
# Ver archivos modificados en último commit
git config --global alias.last "log -1 HEAD --stat"
# Ver branches ordenados por fecha de modificación
git config --global alias.recent "branch --sort=-committerdate --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))'"
Aliases de Limpieza:
# Limpiar branches merged
git config --global alias.cleanup "!git branch --merged | grep -v '\\*\\|main\\|master\\|develop' | xargs -n 1 git branch -d"
# Eliminar branches remotos eliminados localmente
git config --global alias.prune-remote "remote prune origin"
# Unstage todos los archivos
git config --global alias.unstage "reset HEAD --"
# Deshacer último commit manteniendo cambios
git config --global alias.undo "reset --soft HEAD~1"
Aliases de Información:
# Ver contribuciones por autor
git config --global alias.contrib "shortlog --summary --numbered"
# Ver archivos ignorados que están tracked
git config --global alias.ignored "ls-files --others --i --exclude-standard"
# Encontrar commits que modificaron archivo específico
git config --global alias.find-file "log --all --full-history --"
# Ver quién modificó cada línea (blame mejorado)
git config --global alias.who "blame -w -C -C -C"
Aliases de Workflow:
# Commit con mensaje y push en un comando
git config --global alias.cap "!git add -A && git commit -m"
# Uso: git cap "feat: new feature"
# Sync rápido con remote
git config --global alias.sync "!git fetch origin && git rebase origin/main"
# Crear feature branch
git config --global alias.feature "!f() { git checkout -b feature/$1; }; f"
# Uso: git feature user-auth
# Fix rápido
git config --global alias.fix "!f() { git checkout -b fix/$1; }; f"
# Uso: git fix typo-in-docs
# Publish branch
git config --global alias.publish "!git push -u origin $(git branch --show-current)"
Aliases con Scripts Complejos:
# Configurar en ~/.gitconfig:
[alias]
# Squash todos los commits desde branch point
squash-all = "!f() {
git reset --soft $(git merge-base HEAD ${1-main}) &&
git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\";
}; f"
# Archive branch (tag y delete)
archive = "!f() {
git tag archive/$1 $1 &&
git branch -D $1;
}; f"
# Stats del repositorio
stats = "!git log --shortstat --author=\"$(git config user.name)\"
| grep -E 'files? changed'
| awk '{files+=$1; inserted+=$4; deleted+=$6}
END {print \"Files changed:\", files,
\"Lines inserted:\", inserted, \"Lines deleted:\", deleted}'"
7. Conventional Commits con Automation
Mantén un historial de commits semántico que facilite changelogs automáticos.
Formato de Conventional Commits:
# Estructura básica
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
# Tipos estándar:
feat: Nueva funcionalidad
fix: Corrección de bug
docs: Cambios en documentación
style: Formato (no afecta código)
refactor: Refactorización
perf: Mejora de performance
test: Tests
chore: Mantenimiento/config
# Breaking changes
feat!: descripción # ! indica breaking change
feat(api)!: cambio que rompe compatibilidad
BREAKING CHANGE: descripción en footer
Ejemplos Prácticos:
# Feature con scope
git commit -m "feat(auth): add OAuth2 authentication"
# Fix con referencia a issue
git commit -m "fix(api): handle null values in user endpoint
Fixes #123"
# Performance improvement
git commit -m "perf(database): optimize query with indexes"
# Breaking change
git commit -m "feat(api)!: change response format to JSON API spec
BREAKING CHANGE: API responses now follow JSON API specification.
Clients need to update parsing logic."
# Múltiples cambios relacionados
git commit -m "refactor(user): restructure user module
- Extract validation logic
- Improve error handling
- Add comprehensive tests
Relates to #456"
Setup de Commitizen:
# Instalar Commitizen
npm install -g commitizen cz-conventional-changelog
# Configurar en proyecto
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc
# Usar en lugar de git commit
git cz
# Commitizen guía interactivamente a crear commit correcto
Commitlint para Validación:
# Instalar commitlint
npm install --save-dev @commitlint/cli @commitlint/config-conventional
# Configurar
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
# Integrar con Husky
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'
# Ahora commits mal formados serán rechazados:
# ❌ git commit -m "Fixed bug"
# ✅ git commit -m "fix: resolve authentication issue"
Configuración Personalizada:
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', [
'feat', // Nueva característica
'fix', // Corrección de errores
'docs', // Documentación
'style', // Formateo
'refactor', // Refactorización de código
'perf', // Rendimiento
'test', // Pruebas
'build', // Sistema de compilación
'ci', // CI/CD
'chore', // Mantenimiento
'revert' // Revertir commit
]],
'scope-enum': [2, 'always', [
'api',
'ui',
'auth',
'database',
'config'
]],
'subject-max-length': [2, 'always', 72],
'body-max-line-length': [2, 'always', 100]
}
};
### Generar Changelog Automático:
```bash
# Instalar standard-version
npm install --save-dev standard-version
# Agregar script a package.json
{
"scripts": {
"release": "standard-version"
}
}
# Generar release y changelog
npm run release
# Genera:
# - Incremento de versión en package.json
# - Actualización automática de CHANGELOG.md
# - Creación de etiqueta git
# - Generación de commit de release
# Tipos de release:
npm run release -- --release-as minor # 1.0.0 → 1.1.0
npm run release -- --release-as major # 1.1.0 → 2.0.0
npm run release -- --release-as patch # 1.1.0 → 1.1.1
CHANGELOG Generado Automáticamente:
# Changelog
## [2.1.0] - 2025-01-15
### Características
- **auth**: agregar autenticación OAuth2 ([a1b2c3d](link))
- **api**: implementar límite de tasa ([d4e5f6g](link))
### Corrección de Errores
- **api**: manejar valores nulos en punto de usuario ([h7i8j9k](link))
- **ui**: corregir diseño responsivo en móvil ([k0l1m2n](link))
### Mejoras de Rendimiento
- **database**: optimizar consultas con índices ([n3o4p5q](link))
### CAMBIOS SIGNIFICATIVOS
- **api**: cambiar formato de respuesta a especificación JSON API
Configuración Integral: Git Config Completo
Archivo de configuración optimizado para máxima productividad:
# ~/.gitconfig
[user]
name = Tu Nombre
email = tu.email@example.com
[core]
editor = code --wait
autocrlf = input
excludesfile = ~/.gitignore_global
pager = delta # mejor visualizador de diferencias
[pull]
rebase = true # rebase por defecto al hacer pull
[push]
default = current
autoSetupRemote = true # configuración automática de seguimiento
[fetch]
prune = true # limpiar referencias automáticamente
[rebase]
autosquash = true
autoStash = true
[merge]
conflictstyle = diff3 # mejor resolución de conflictos
tool = vscode
[diff]
algorithm = histogram # mejor algoritmo de diferencias
colorMoved = zebra
[blame]
coloring = highlightRecent
[help]
autocorrect = 10 # auto-corrección de errores tipográficos después de 1 segundo
[alias]
# (Incluir todos los alias del tip #6)
Ignorar Archivos Globalmente:
# ~/.gitignore_global
# Sistemas Operativos
.DS_Store
Thumbs.db
# IDEs
.vscode/
.idea/
*.swp
*.swo
# Dependencias
node_modules/
vendor/
# Salidas de compilación
dist/
build/
*.log
# Entorno
.env
.env.local
Plan de Implementación Semanal
Semana 1: Fundamentos
- Configurar git config con alias básicos
- Practicar rebase interactivo en branch de feature
- Configuración de commitlint con Husky
Semana 2: Workflows Avanzados
- Crear worktree para revisión de código
- Usar git bisect para encontrar regresión
- Configurar flujo de trabajo de stash personalizado
Semana 3: Automatización
- Configuración de Commitizen para commits convencionales
- Configurar standard-version para changelogs
- Crear alias personalizados para tu flujo de trabajo
Semana 4: Optimización
- Documentar flujos de trabajo para el equipo
- Refinar hooks de git según necesidades
- Establecer convenciones de branches y commits
Métricas de Éxito
Antes de implementar técnicas avanzadas:
- Tiempo en resolución de conflictos: ~30min promedio
- Commits por feature: ~15 commits desordenados
- Time to recovery de errores: ~45min
- Mantenimiento de changelog: Manual y desactualizado
Después de implementar:
- Tiempo en resolución de conflictos: ~10min promedio (-67%)
- Commits por feature: 3-5 commits organizados (-70%)
- Time to recovery: ~5min con reflog (-89%)
- Changelog: Automático y actualizado
Desafío de la Semana
Implementa al menos 3 técnicas esta semana:
- Rebase Interactivo: Limpia el historial de tu branch de feature actual
- Git Worktrees: Crea un worktree para revisión de código sin perder contexto
- Commits Convencionales: Configura commitlint y usa formato estándar
- Alias de Git: Crea 5 alias que uses en tu flujo de trabajo diario
- Git Bisect: Usa bisect la próxima vez que encuentres una regresión
Bonus: Configura generación automática de changelog y comparte tu primer CHANGELOG.md generado automáticamente.
Git es mucho más que commit y push. Dominar estas técnicas avanzadas transforma Git de una herramienta básica de control de versiones a un sistema poderoso que optimiza colaboración, depuración y calidad del código.
¿Cuáles de estas técnicas ya usan en sus flujos de trabajo? ¿Qué comandos de Git consideran indispensables que pocos conocen?
techtipsmonday git #ControlDeVersiones #Productividad #FlujoDeTrabajo #HerramientasDeDesarrollo #BuenasPrácticas