🔄 El Sendero del Pulso: pull, push y SSH Keys

“Un ninja aislado es un ninja débil. La fuerza verdadera reside en la conexión con el Templo, donde el conocimiento fluye como un río eterno.” - Maestro de Redes

🎯 La Filosofía de la Sincronización

Tu código local es tu dojo personal. GitHub es el Templo Central donde todos los ninjas comparten sus técnicas. Para que ambos mundos estén alineados, necesitas:

  1. git push: Enviar tus técnicas locales al Templo
  2. git pull: Traer las técnicas de otros ninjas a tu dojo
  3. SSH Keys: La llave secreta que te identifica sin contraseñas

Sin sincronización, estás entrenando en soledad. Con sincronización, participas en el Jutsu Colectivo del equipo.


📜 El Camino del Conocimiento

Parte 1: El Arte del Push (Enviar Cambios)

git push sube tus commits locales al repositorio remoto.

Flujo básico:

# 1. Haz cambios en tu código
echo "Nueva técnica ninja" >> jutsu.md

# 2. Stage y commit
git add jutsu.md
git commit -m "feat: añadir técnica de invisibilidad"

# 3. Envía al remoto (origin = GitHub, main = rama)
git push origin main

Primera vez en una rama nueva:

# Crear rama local
git checkout -b feature/nueva-habilidad

# Primer push (crea la rama en GitHub)
git push -u origin feature/nueva-habilidad
# El flag -u (upstream) conecta tu rama local con la remota

# Siguientes pushes en esta rama (ya no necesitas especificar)
git push

Casos especiales:

# Forzar push (CUIDADO: sobrescribe historia remota)
git push --force
# ⚠️ SOLO usa esto si estás 100% seguro. Puede borrar trabajo de otros.

# Push más seguro (falla si alguien más subió cambios)
git push --force-with-lease

# Push de TODAS las ramas locales
git push --all origin

# Push de todos los tags
git push --tags

Errores comunes y soluciones:

Error 1: “Updates were rejected”

# Problema: El remoto tiene commits que tú no tienes
# Solución:
git pull origin main --rebase  # Trae cambios y reaplica los tuyos encima
git push origin main

Error 2: “Authentication failed”

# Problema: No tienes permisos o credenciales incorrectas
# Solución: Configura SSH (ver Parte 3) o usa Personal Access Token

Parte 2: El Arte del Pull (Recibir Cambios)

git pull descarga commits del remoto y los fusiona con tu rama local.

Anatomía del pull:

# Pull = Fetch + Merge
git pull origin main

# Es equivalente a:
git fetch origin        # Descarga cambios sin tocar tu código
git merge origin/main   # Fusiona los cambios descargados

Estrategias de pull:

1. Pull con merge (default):

git pull origin main
# Crea un merge commit si hay divergencia

2. Pull con rebase (historia más limpia):

git pull --rebase origin main
# Mueve tus commits locales encima de los remotos

Configurar rebase como default:

git config --global pull.rebase true
# Ahora todos tus pulls harán rebase automáticamente

Workflow diario recomendado:

# Al comenzar el día:
git switch main
git pull origin main                    # Actualiza main

git switch feature/tu-rama
git rebase main                         # Actualiza tu rama con cambios de main

# Trabajas todo el día...

# Al terminar:
git add .
git commit -m "feat: implementar X"
git push origin feature/tu-rama

Fetch vs Pull:

# FETCH: Solo descarga, NO modifica tu código
git fetch origin
git log origin/main  # Ver qué cambios hay sin aplicarlos
git merge origin/main # Decidir si fusionar

# PULL: Descarga Y fusiona automáticamente
git pull origin main

Parte 3: SSH Keys - La Llave del Templo

¿Por qué SSH?

  • Sin contraseñas: No te pide credenciales en cada push/pull
  • Más seguro: Usa criptografía de clave pública/privada
  • Profesional: Es el estándar en empresas

Generar tu par de llaves SSH:

# 1. Verifica si ya tienes llaves
ls -la ~/.ssh
# Busca archivos: id_rsa.pub, id_ed25519.pub

# 2. Si NO tienes, genera un nuevo par
ssh-keygen -t ed25519 -C "tu-email@ejemplo.com"
# Presiona Enter 3 veces (ubicación default, sin passphrase para facilidad)

# 3. Inicia el agente SSH
eval "$(ssh-agent -s)"

# 4. Añade la llave al agente
ssh-add ~/.ssh/id_ed25519

Formato de las llaves:

~/.ssh/
├── id_ed25519          # Llave PRIVADA (NUNCA la compartas)
└── id_ed25519.pub      # Llave PÚBLICA (esta la subes a GitHub)

Añadir SSH key a GitHub:

# 1. Copia la llave pública al portapapeles
# En macOS:
pbcopy < ~/.ssh/id_ed25519.pub

# En Linux:
cat ~/.ssh/id_ed25519.pub
# Selecciona y copia el output

# En Windows (Git Bash):
clip < ~/.ssh/id_ed25519.pub

2. En GitHub:

  1. Ve a Settings > SSH and GPG keys
  2. Click “New SSH key”
  3. Título: Mi MacBook Pro (identifica el dispositivo)
  4. Key type: Authentication Key
  5. Pega la llave pública
  6. Click “Add SSH key”

Verificar la conexión:

ssh -T git@github.com
# Output esperado:
# "Hi tu-usuario! You've successfully authenticated..."

Cambiar remoto de HTTPS a SSH:

# Ver remoto actual
git remote -v
# origin  https://github.com/user/repo.git (fetch)

# Cambiar a SSH
git remote set-url origin git@github.com:user/repo.git

# Verificar
git remote -v
# origin  git@github.com:user/repo.git (fetch)

Múltiples cuentas de GitHub (Avanzado):

Si tienes cuenta personal y laboral:

# Edita ~/.ssh/config
nano ~/.ssh/config
# Cuenta personal
Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_personal

# Cuenta de trabajo
Host github-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_work
# Clonar con cuenta personal
git clone git@github.com:personal-user/repo.git

# Clonar con cuenta de trabajo
git clone git@github-work:company-user/repo.git

Parte 4: Workflows de Equipo

Sincronización en equipos:

# Regla de oro: SIEMPRE pull antes de push

# ❌ MAL (puede causar conflictos)
git add .
git commit -m "fix: bug"
git push

# ✅ BIEN
git pull --rebase origin main
git add .
git commit -m "fix: bug"
git push origin main

Manejo de merge conflicts durante pull:

git pull origin main
# Auto-merging archivo.js
# CONFLICT (content): Merge conflict in archivo.js

# 1. Resuelve conflictos manualmente (ver módulo 3.2)
# 2. Marca como resuelto
git add archivo.js

# 3. Continúa el rebase (si usaste --rebase)
git rebase --continue

# O completa el merge
git commit -m "merge: resolver conflictos de pull"

Stash para guardar cambios temporales:

# Guardas trabajo sin commitear
git stash

# Actualizas desde remoto
git pull origin main

# Recuperas tu trabajo
git stash pop

# Ver todos los stashes
git stash list

# Aplicar un stash específico
git stash apply stash@{1}

💡 Jutsu Secreto: Git Hooks para Automatización

Los hooks ejecutan scripts antes/después de acciones Git.

Ejemplo: Prevenir push a main desde local

# Archivo: .git/hooks/pre-push
#!/bin/bash

protected_branch='main'
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')

if [ $current_branch = $protected_branch ]; then
    echo "🚫 No puedes hacer push directo a $protected_branch"
    echo "Crea un PR desde una rama feature"
    exit 1
fi

exit 0
# Hacerlo ejecutable
chmod +x .git/hooks/pre-push

Hooks útiles:

  • pre-commit: Ejecutar linters antes de commit
  • pre-push: Correr tests antes de push
  • post-merge: Instalar dependencias después de pull

🎯 Reto Ninja del Tema

Misión: Configurar SSH y simular trabajo en equipo

Parte 1: SSH Setup

  1. Genera un par de llaves SSH (si no tienes)
  2. Añádela a GitHub
  3. Crea un nuevo repo llamado ssh-dojo
  4. Clónalo usando SSH (no HTTPS)
  5. Haz un cambio y push sin que te pida contraseña

Parte 2: Simulación de Conflicto

  1. En GitHub: Edita el README.md directamente (cambia una línea)
  2. En local: Edita la MISMA línea del README.md
  3. Intenta hacer push (fallará porque el remoto está adelantado)
  4. Haz pull (habrá conflicto)
  5. Resuelve el conflicto y push exitoso

Parte 3: BONUS

  • Configura git pull.rebase true como default
  • Crea un alias git sync que haga pull --rebase && push

Criterios de éxito:

  • ✅ Tu primera autenticación SSH fue exitosa
  • ✅ Puedes hacer push sin ingresar contraseñas
  • ✅ Resolviste el conflicto de pull correctamente
  • ✅ El historial en GitHub refleja todos los cambios

📚 Recursos Adicionales


Siguiente Pergamino: 3.4 La Taberna de las Misiones - Issues, Labels, Milestones

¿Configuraste SSH? Comparte una captura de ssh -T git@github.com en Discord con #SSHNinja! 🔐🥷