🌳 Las Ramas del Destino: branch, checkout, merge y conflictos

“Un ninja sabio no ataca directamente la aldea principal. Primero entrena en un campo de batalla alterno, perfecciona su técnica, y solo entonces la presenta al Hokage.” - Código del Shinobi

🎯 La Filosofía de las Líneas Temporales

Imagina que puedes clonar tu realidad para experimentar sin consecuencias. En Git, esto se llama branch (rama). Puedes:

  • Desarrollar una nueva funcionalidad sin romper el código en producción
  • Probar 3 enfoques diferentes en paralelo
  • Aislar bugs críticos para corregirlos sin contaminar el trabajo en curso

El flujo ninja moderno sigue este patrón sagrado:

main (producción, código sagrado, intocable)

develop (desarrollo activo, aquí vive el caos controlado)

feature/nueva-funcionalidad (tu experimento temporal)

📜 El Camino del Conocimiento

Parte 1: Crear y Navegar entre Ramas

Ver todas las ramas:

# Listar ramas locales
git branch

# Listar TODAS (locales + remotas)
git branch -a

# Ver la rama actual con más info
git status

Crear una nueva rama:

# Método clásico (crear pero NO cambiarse)
git branch feature/login-ninja

# Método moderno (crear Y cambiarse en un solo movimiento)
git checkout -b feature/login-ninja

# Método ultra-moderno (Git 2.23+)
git switch -c feature/login-ninja

💡 Nomenclatura profesional de ramas:

# ✅ BUENAS PRÁCTICAS
feature/autenticacion-jwt      # Nueva funcionalidad
bugfix/error-404-usuarios      # Corrección de bug
hotfix/vulnerabilidad-xss      # Parche urgente en producción
refactor/optimizar-queries     # Mejora de código sin cambiar funcionalidad
docs/actualizar-readme         # Solo documentación

# ❌ MALAS PRÁCTICAS
mi-rama                        # ¿Qué hace?
test                           # Muy genérico
nueva-cosa-123                 # Sin contexto

Cambiar entre ramas:

# Método clásico
git checkout main

# Método moderno (más semántico)
git switch main

# Volver a la rama anterior (como cd -)
git switch -

⚠️ REGLA DE ORO: Antes de cambiar de rama, asegúrate de que no tienes cambios sin guardar:

# ❌ ESTO FALLARÁ si tienes cambios pendientes
git switch otra-rama

# ✅ SOLUCIÓN 1: Guardar cambios
git add .
git commit -m "wip: trabajo en progreso"

# ✅ SOLUCIÓN 2: Ocultar temporalmente (stash)
git stash
git switch otra-rama
# ... haces otras cosas ...
git switch -
git stash pop  # Recupera tus cambios

Parte 2: Fusionar Ramas (Merge)

Cuando terminas tu trabajo en una rama experimental, debes fusionarla de vuelta a la rama principal.

Flujo básico de merge:

# 1. Cambiar a la rama que RECIBIRÁ los cambios
git switch main

# 2. Asegurarte de estar actualizado
git pull origin main

# 3. Fusionar la rama feature
git merge feature/login-ninja

# 4. Subir los cambios fusionados
git push origin main

Tipos de merge:

1. Fast-Forward (sin conflictos, historia lineal):

# Ocurre cuando main no ha cambiado desde que creaste la rama
git merge feature/nueva-funcion
# Output: "Fast-forward"
Antes:
main:     A---B
               \
feature:        C---D

Después:
main:     A---B---C---D

2. Three-Way Merge (crea un commit de fusión):

# Ocurre cuando ambas ramas tienen commits nuevos
git merge feature/otra-cosa
# Git crea automáticamente un "merge commit"
Antes:
main:     A---B---E
               \
feature:        C---D

Después:
main:     A---B---E---F (merge commit)
               \     /
feature:        C---D

Eliminar rama después de fusionar:

# Borrar rama local (solo si ya fue fusionada)
git branch -d feature/login-ninja

# Forzar borrado (aunque NO esté fusionada)
git branch -D experimento-fallido

# Borrar rama remota en GitHub
git push origin --delete feature/login-ninja

Parte 3: Resolver Conflictos (El Jutsu Definitivo)

Un conflicto ocurre cuando dos ramas modifican la misma línea del mismo archivo. Git no puede decidir automáticamente cuál versión mantener.

Escenario típico:

# En rama main: cambias "título" a "Bienvenido Ninja"
# En rama feature: cambias "título" a "Hola Samurái"
# Intentas fusionar...
git merge feature/nuevo-titulo
# ¡CONFLICTO!

Cómo se ve un conflicto en tu archivo:

<!DOCTYPE html>
<html>
  <head>
<<<<<<< HEAD (rama actual: main)
    <title>Bienvenido Ninja</title>
=======
    <title>Hola Samurái</title>
>>>>>>> feature/nuevo-titulo (rama que intentas fusionar)
  </head>
</html>

Resolver el conflicto paso a paso:

# 1. Git te muestra qué archivos tienen conflictos
git status
# Output: "both modified: index.html"

# 2. Abre el archivo y edítalo manualmente
# DECIDE qué versión mantener (o combina ambas)

# 3. Elimina las marcas de conflicto (<<<<, ====, >>>>)
# Deja solo el código final que quieres:
<title>Bienvenido Ninja Samurái</title>

# 4. Marca el conflicto como resuelto
git add index.html

# 5. Completa el merge con un commit
git commit -m "merge: fusionar feature/nuevo-titulo, combinar títulos"

💡 Pro tip: Usar herramientas visuales

# Configurar VS Code como herramienta de merge
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'

# Cuando haya conflicto, ejecuta:
git mergetool
# Se abre VS Code con interfaz gráfica para elegir versiones

Herramientas populares de merge:

  • VS Code: Plugin “GitLens” + vista de merge nativa
  • Meld: GUI multiplataforma
  • KDiff3: Comparación de 3 vías
  • P4Merge: Gratuita y poderosa

Parte 4: Estrategias Avanzadas

Merge vs Rebase (el debate eterno):

# MERGE: Mantiene historial completo (más seguro para principiantes)
git merge feature/x
# Crea un commit de merge, historia se bifurca

# REBASE: Reescribe historial, historia lineal (para ninjas avanzados)
git rebase main
# "Mueve" tus commits encima de main, como si siempre hubieran estado ahí

Cuándo usar cada uno:

SituaciónUsa
Rama pública/compartidamerge (nunca reescribas historia pública)
Rama personal/localrebase (mantén historial limpio)
Feature terminadamerge (preserva contexto de cuándo se integró)
Actualizar tu rama con mainrebase (evita commits de merge innecesarios)

Abortar un merge problemático:

# Si todo está saliendo mal, resetea al estado previo
git merge --abort

# O si ya commiteaste pero quieres deshacerlo
git reset --hard HEAD~1  # ¡CUIDADO! Esto BORRA cambios

💡 Jutsu Secreto: Alias para Workflows Rápidos

Agrega estos alias a tu .gitconfig para ser más eficiente:

# Editar config global
git config --global alias.sw switch
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.cm 'commit -m'
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --all --decorate"

# Crear feature branch desde main actualizado
git config --global alias.feature '!git switch main && git pull && git switch -c'

# Uso:
git feature nueva-funcionalidad
# Equivale a:
# git switch main
# git pull
# git switch -c nueva-funcionalidad

Oh My Zsh plugins útiles:

# En tu ~/.zshrc
plugins=(git gitfast git-flow)

# Shortcuts automáticos:
gco = git checkout
gcm = git commit -m
gst = git status
gp = git push
gl = git pull

🎯 Reto Ninja del Tema

Misión: Simular un flujo de desarrollo real con conflictos

  1. Crea un repositorio llamado ninja-merge-dojo
  2. Inicializa con un README.md que contenga:
    # Dojo de Fusiones
    Maestro: [Tu nombre]
    Técnica actual: Ninguna
  3. Crea dos ramas:
    • jutsu-fuego: Cambia “Técnica actual” a “Bola de Fuego”
    • jutsu-agua: Cambia “Técnica actual” a “Dragón de Agua”
  4. Fusiona jutsu-fuego a main (debería ser fast-forward)
  5. Intenta fusionar jutsu-agua a main (¡CONFLICTO!)
  6. Resuelve el conflicto combinando ambas técnicas:
    Técnica actual: Bola de Fuego + Dragón de Agua (Jutsu Combinado)
  7. Visualiza el historial con git log --oneline --graph --all
  8. BONUS: Crea una rama bugfix/typo, corrige un error de ortografía y fusiónala

Criterios de éxito:

  • ✅ Tienes al menos 3 ramas creadas en el proceso
  • ✅ Resolviste el conflicto sin marcas residuales (<<<<, ====)
  • ✅ El historial muestra al menos 2 merges
  • ✅ Las ramas temporales fueron eliminadas después de fusionar

📚 Recursos Adicionales


Siguiente Pergamino: 3.3 El Sendero del Pulso - pull, push, SSH

¿Completaste el reto? Comparte una captura de tu git log --graph en Discord con #RamasNinja! 🌳🥷