GitHub Workflow — Guía Completa
Flujo completo de trabajo con GitHub para agentes IA.
Tabla de Contenidos
- Autenticación — Tokens, SSH, gh CLI
- Gestión de Repos — Clone, create, fork, remotes
- PR Lifecycle — Branch, commit, open, CI, merge
- Code Review — Diffs, inline comments, gh CLI
- Issues — Create, triage, label, assign
- Knowledge Repo — Base de conocimiento persistente
- GitHub Pages — Deploy estático
- Repo Recovery — Remote overwritten, force push restore
- Branch Rename + Pages Reconfig — master→main completo
- Environment Protection Rules — Pitfall con deployment_branch_policy
- Deploy Pages para Repo EXISTENTE — Verificar existencia antes de crear
- Deploy Estático desde Cero — Crear repo + push + activar Pages
1. Autenticación
GitHub CLI:
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg 2>/dev/null
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null
apt-get update -qq && apt-get install -y -qq gh
Auth con token:
token=$(grep GITHUB_TOKEN /hermes-home/.env | cut -d= -f2-)
# ⚠️ GH CLI falla con GITHUB_TOKEN env var set
GITHUB_TOKEN="" echo "$token" | gh auth login --with-token
2. Gestión de Repos
git clone https://github.com/OWNER/REPO.git
git remote add upstream https://github.com/ORIGINAL/REPO.git
git fetch upstream && git merge upstream/main
3. PR Lifecycle
git checkout -b feature/titulo
# ... changes ...
git add -A && git commit -m "feat: description"
git push -u origin feature/titulo
gh pr create --title "feat: title" --body "description"
gh pr merge --auto # auto-merge si CI pasa
4. Code Review
gh pr diff 123 # Ver diff
gh pr comments 123 # Ver comentarios
gh pr review 123 --approve # Aprobar
gh pr review 123 --comment -b "feedback" # Comentar
5. Issues
gh issue create --title "Bug: ..." --body "description" --label "bug"
gh issue list --state open
gh issue edit 456 --add-label "priority-high"
6. Knowledge Repo
Usar un repos GitHub como base de conocimiento persistente:
notes/— Notas con formatoYYYY-MM-DD-titulo.mdmastermind/oskills/— SKILL.md filesmemory/— Backups de memoriascripts/— Automatizacionesconfig/— Configuraciones
Sync: git pull → cp -n mastermind/*.md /hermes-home/skills/mastermind/
7.0 Decidir: GitHub Pages vs NaN
| Criterio | GitHub Pages | NaN.builders |
|---|---|---|
| Estático puro (HTML/CSS/JS) | ✅ Ideal — gratis, simple | ❌ Overkill |
| Node.js backend | ❌ No soportado | ✅ Necesario |
| APIs/proxy CORS | ❌ No (usar proxy público) | ✅ Servidor propio |
| Variables de entorno | ❌ No | ✅ Sí |
| Velocidad deploy | 1-2 min (workflow) | 2-5 min (Kaniko) |
| Control total | Limitado | Completo |
Regla: Estáticos puros → GitHub Pages. Todo lo que necesite servidor → NaN.
7.0b Pitfall: GitHub Pages legacy + /dashboard path
Cuando GitHub Pages está en modo legacy con source.path: "/":
- Solo acepta
/o/docscomo paths./dashboarddevuelve 422. - El PUT no cambia el build_type automáticamente — sigue en legacy.
Solución A — iframe en index.html raíz (fallback inmediato):
<!DOCTYPE html>
<html lang="es">
<head><meta charset="UTF-8"><title>Título</title></head>
<body>
<iframe src="./dashboard/index.html" style="width:100vw;height:100vh;border:none;margin:0;padding:0;"></iframe>
</body>
</html>
Funciona inmediatamente sin cambiar build_type. El workflow de Pages puede seguir existiendo sin conflictos.
Solución B — Intentar activar workflow primero:
- Crear
.github/workflows/pages.ymlconactions/deploy-pages@v4 - Commit + push
- Esperar 60s, verificar con
curl - Si sigue
errored→ usar iframe como fallback
Verificar estado de Pages:
curl -s https://api.github.com/repos/OWNER/REPO/pages \
-H "Authorization: token $TOKEN" | jq '{build_type, status, source}'
# build_type: "legacy" + status: "errored" = bloqueado con paths nuevos
Pitfalls:
- El workflow dispatch manual (
POST /actions/workflows/X/dispatches) devuelve 422 si el workflow NO tieneworkflow_dispatchen su trigger — no es error de deploy GET /repos/.../pagesmuestrabuild_type: "legacy"+status: "errored"= bloqueado con paths nuevosPOST /repos/.../pagesconbuild_type: "workflow"devuelve 409 si Pages ya está activoPUT /repos/.../pagesconsource.path: "/dashboard"devuelve 422 si está en legacy mode
7. GitHub Pages
7.1 Deploy básico
Activar Pages via API REST (sin gh CLI):
import urllib.request, json
token = '' # leer de .env
data = json.dumps({"build_type": "workflow"}).encode()
req = urllib.request.Request(
'https://api.github.com/repos/OWNER/REPO/pages',
data=data,
headers={
'Authorization': f'token {token}',
'Accept': 'application/vnd.github.v3+json',
'Content-Type': 'application/json'
},
method='POST'
)
resp = urllib.request.urlopen(req)
print(json.loads(resp.read())['html_url'])
# → https://OWNER.github.io/REPO/
Activar con gh CLI:
gh api repos/:owner/:repo/pages -X POST \
-f source.branch=main -f source.path=/
Pitfall: build_type: "workflow" requiere que exista un workflow de GitHub Actions que use actions/deploy-pages@v4. Si el workflow no existe, el deploy falla silenciosamente.
7.1a Fix: legacy → workflow via PUT (cuando POST devuelve legacy stuck)
El POST a /pages a menudo devuelve build_type: "legacy" aunque el repo tenga un workflow de Pages. Legacy puede quedarse en status: "building" indefinidamente (probado con HTML de 138KB). Fix: hacer PUT para forzar build_type: "workflow":
# 1. POST activa Pages (devuelve build_type: legacy)
curl -s -X POST https://api.github.com/repos/OWNER/REPO/pages \
-H "Authorization: token $TOKEN" \
-d '{"source":{"branch":"main","path":"/"}}'
# → build_type: "legacy", status: "building"
# 2. PUT cambia a workflow mode (204 = OK)
curl -s -X PUT https://api.github.com/repos/OWNER/REPO/pages \
-H "Authorization: token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"source":{"branch":"main","path":"/"},"build_type":"workflow"}'
# → 204 = success
# 3. Esperar y verificar
sleep 30
curl -s -o /dev/null -w "%{http_code}" https://OWNER.github.io/REPO/
# → 200
Pitfall: El PUT requiere que el workflow de Pages YA exista en el repo (commit + push antes de activar Pages). Si el workflow no existe, el PUT falla o el deploy falla silenciosamente.
Secuencia completa correcta para activar Pages en repo estático existente:
- Crear
.nojekyllen raíz - Crear
.github/workflows/pages.ymlconactions/deploy-pages@v4 - Commit + push
POST /repos/.../pages→ activa (devuelve legacy)PUT /repos/.../pagesconbuild_type: "workflow"→ corrige- Verificar con
curl -sI
7.1b Deploy ultra-rápido con branch gh-pages (HTML puro, sin build)
Para un HTML estático SIN build step (sin Vite, sin Node.js), el deploy más rápido es usar el branch gh-pages directamente. No requiere workflow de Actions, no requiere esperar a que GitHub Pages "active" el sitio.
Pasos:
# 1. Crear branch gh-pages desde main (con el HTML ya en la raíz)
git checkout -b gh-pages
git push origin gh-pages
# 2. Activar Pages via API apuntando a gh-pages
curl -X POST https://api.github.com/repos/OWNER/REPO/pages \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-d '{"branch":"gh-pages","source":{"branch":"gh-pages","path":"/"}}'
# 3. Esperar build y verificar
sleep 45
curl -sI https://OWNER.github.io/REPO/ | head -1
# → HTTP/2 200
Ventajas sobre workflow de Actions:
- Sin necesidad de crear
.github/workflows/pages.yml - Sin environment protection rules que puedan bloquear
- Sin
actions/deploy-pages@v4que pueda fallar - Build más rápido (GitHub Pages construye directamente el branch)
Pitfall: Si Pages ya estaba activado (por un workflow anterior), el POST devuelve 409 ("Pages is already enabled"). En ese caso, el branch gh-pages ya se usa y no hace falta la llamada API.
Pitfall: Si el workflow de Actions existe pero falla, el branch gh-pages sigue siendo una alternativa válida.
7.2 Workflow para sites estáticos
Crear .github/workflows/pages.yml:
name: Desplegar a GitHub Pages
on:
push:
branches: ["master"] # o "main"
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: '.'
- uses: actions/deploy-pages@v4
id: deployment
Pitfall: Para sites estáticos HTML (sin build), crear .nojekyll en la raíz del repo para evitar que GitHub procese con Jekyll.
7.2a Deploy con datos JSON + frontend separados (patrón CIAF-visor)
Cuando el proyecto tiene frontend/ y data/ como directorios separados, no deployes solo frontend/ — los fetch a ../data/ fallarán. Solución: copiar datos al directorio de deploy en el workflow.
- name: Prepare deployment
run: |
mkdir -p deploy/data
cp -r frontend/* deploy/
cp -r data/reports data/memorias data/train-tracks.geojson data/index.json data/relations.json deploy/data/
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'deploy/'
Y en el HTML, usar rutas relativas al root: fetch('data/index.json') en vez de fetch('../data/index.json').
Pitfall: GitHub Pages solo sirve lo que esté en el directorio de deploy. Los directorios no incluidos (como scripts/, pdfs/) no están accesibles vía URL.
7.2 Vite + GitHub Pages con Service Worker (patrón crítico)
Cuando usas Vite para build + GH Pages para deploy, hay 4 problemas que se repiten:
7.2.1 Service Worker no se despliega
Vite solo procesa lo que rollup toca. El SW (sw.js) existe en la raíz del repo pero no se copia al dist/ automáticamente.
Fix: Añadir copia manual en postbuild.js:
// postbuild.js
const swSrc = path.join(__dirname, 'sw.js');
const swDest = path.join(distDir, 'sw.js');
if (fs.existsSync(swSrc)) {
fs.copyFileSync(swSrc, swDest);
}
Asegurar que package.json ejecuta postbuild:
"build": "vite build && node postbuild.js"
7.2.2 Ruta del SW — absoluta vs relativa
❌ navigator.serviceWorker.register('/sw.js') — busca en la raíz del dominio (ntizar.github.io/sw.js), no en el subpath del repo.
✅ navigator.serviceWorker.register('./sw.js') — busca relativo al path del sitio (ntizar.github.io/SistemaElectricoFuturo/sw.js), que es donde realmente está.
7.2.3 STATIC_ASSETS desalineados con el build
El SW típicamente lista assets como /css/app.css, /js/app.js, etc. Pero tras un build de Vite:
- Los CSS pueden ir a
/assets/index-XXXX.css(con hash) - Los JS IIFE pueden estar en
/js/app.jssi se copian con postbuild - Los CSS legacy pueden no existir si Vite los bundlea
Fix: STATIC_ASSETS del SW debe listar solo archivos que realmente existen en dist/ después del build. Si el postbuild copia JS a dist/js/, las rutas en el SW deben coincidir.
const STATIC_ASSETS = [
'/',
'/index.html',
'/js/app.js', // Solo si postbuild.js los copia
// NO '/css/app.css' si Vite lo bundlea a /assets/index-XXXX.css
];
7.2.4 SW cache addAll() → fail silencioso → app rota
Si cache.addAll(STATIC_ASSETS) encuentra un 404 (porque un asset listado no existe), todo el install event falla. El SW nuevo nunca se activa y el navegador sigue usando la caché vieja. Síntoma: fondo blanco, CSS/JS no cargan, hard refresh no funciona.
Diagnóstico: DevTools → Application → Service Workers → ver si el SW nuevo está en estado "waiting" o "errored". Mirar el output de cache.addAll().
Fix (3 pasos obligatorios):
- Eliminar referencias a assets que no existen en
dist/delSTATIC_ASSETS - Bump CACHE_NAME (ej.
v3.4→v4.1) para forzar re-caché completo desde cero - Hard refresh (
Ctrl+Shift+R) o Unregister en DevTools después del deploy
7.3 favicon.ico 404 en GitHub Pages
GitHub Pages busca favicon.ico en la raíz del dominio (ntizar.github.io/favicon.ico), no en el subpath del repo. Si no existe, aparece error 404 en consola.
Fix: Crear favicon.svg en el repo, añadirlo al <head>:
<link rel="icon" type="image/svg+xml" href="favicon.svg">
Y copiarlo al dist/ en el postbuild (igual que el SW).
7.4 CORS proxy para API externas en sitios estáticos
GitHub Pages es hosting estático — no hay backend para hacer proxy. Las APIs que no envían Access-Control-Allow-Origin: * no se pueden llamar directamente desde el navegador.
Patrón: Usar un proxy CORS público como intermediario:
const rawUrl = `https://api-externa.com/data?param=value`;
const proxyUrl = `https://api.allorigins.win/raw?url=${encodeURIComponent(rawUrl)}`;
fetch(proxyUrl)
.then(r => r.text()) // IMPORTANTE: .text() no .json() (allorigins devuelve texto plano)
.then(text => {
const data = JSON.parse(text);
// procesar...
})
.catch(() => null); // fallback silencioso
Alternativas de proxy:
https://api.allorigins.win/raw?url=...✅ probadohttps://corsproxy.io/?url=...https://api.allorigins.win/get?url=...(versión con metadata wrapper)
⚠️ No asumir que el proxy devuelve JSON: allorigins.win devuelve HTML plano a veces. Usar .text() + JSON.parse() para mejorar tolerancia.
7.5 Debugging de errores 404 en GitHub Pages
Cuando un sitio GH Pages muestra fondo blanco o faltan recursos, el flujo de diagnóstico es:
- curl a la página principal →
curl -sI https://user.github.io/repo/→ verificar 200 OK - curl a cada asset referenciado:
curl -sI https://user.github.io/repo/js/app.js | head -3 curl -sI https://user.github.io/repo/assets/index-XXXX.css | head -3 - Inspeccionar el HTML servido →
curl -s https://user.github.io/repo/ | grep -E '(script src|link.*css|sw\.js|favicon)' - Buscar rutas absolutas en el HTML:
/css/...en vez de./css/...o/SistemaElectricoFuturo/css/... - Verificar Service Worker en DevTools → Application → Service Workers → ver si cache.addAll() está fallando
Causas comunes:
- Ruta absoluta
/js/app.jscuando el sitio está en un subpath → 404 - Vite genera
/assets/index-XXXX.csssin prefijo del subpath → 404 - postbuild.js no copia assets necesarios (SW, favicon, CSS legacy)
- SW cacheado sirve assets viejos que ya no existen → bump CACHE_NAME
8. Repo Recovery
Cuando el remote fue reemplazado con un repositorio mínimo:
- Backup local:
cp -r repo /tmp/repo-backup - Reset local:
git reset --hard origin/main - Restaurar backup:
rm -rf repo && cp -r /tmp/repo-backup repo - Force push:
git push origin main --force
⚠️ Siempre backup primero. Force push es destructivo.
Linked Files
references/environment-protection-rules.md— Pitfall con environment protection rules al renombrar branchreferences/branch-merge-selectivo-mastermind.md— Fusión inteligente de dos ramasreferences/deploy-existing-repo.md— Verificar existencia de repo antes de crear (nueva)
9. Branch Rename + GitHub Pages Reconfig
Al renombrar branch de master a main, hay 3 pasos obligatorios para que Pages siga funcionando:
Paso 1: Actualizar workflow YAML
Cambiar branches: ["master"] → branches: ["main"] en .github/workflows/pages.yml.
Paso 2: Actualizar Pages via API PUT
import urllib.request, json
data = json.dumps({
"source": {"branch": "main", "path": "/"},
"build_type": "workflow"
}).encode()
req = urllib.request.Request(
'https://api.github.com/repos/OWNER/REPO/pages',
data=data,
headers={
'Authorization': f'token {TOKEN}',
'Accept': 'application/vnd.github.v3+json',
'Content-Type': 'application/json'
},
method='PUT' # PUT, no POST
)
urllib.request.urlopen(req) # 204 = OK
Paso 3: Dispatch manual del workflow
data = json.dumps({"ref": "main"}).encode()
req = urllib.request.Request(
'https://api.github.com/repos/OWNER/REPO/actions/workflows/PAGE-SLUG.yml/dispatches',
data=data,
headers={
'Authorization': f'token {TOKEN}',
'Accept': 'application/vnd.github.v3+json',
'Content-Type': 'application/json'
},
method='POST'
)
urllib.request.urlopen(req) # 204 = dispatched
Pitfall: Si solo cambias el branch en el workflow pero no actualizas Pages via API, el deploy seguirá apuntando a master y fallará silenciosamente.
Pitfall: El workflow dispatch debe ser al archivo correcto (PAGE-SLUG.yml, no siempre "pages.yml").
10. GitHub Pages + environment protection rules (Pitfall crítico)
Cuando un workflow de GitHub Pages usa environment: github-pages, el entorno puede tener reglas de protección de rama (deployment_branch_policy) que solo permiten master. Al renombrar a main, el deploy falla con:
Branch "main" is not allowed to deploy to github-pages due to environment protection rules.
Diagnóstico: El workflow termina en failure en 2-5 segundos (demasiado rápido para un deploy real). Revisar annotations del job.
Solución A — Eliminar el entorno:
# DELETE /repos/{owner}/{repo}/environments/{env_name}
# Esto elimina las reglas de protección y permite deploy sin restricciones
Solución B — Usar workflow sin environment:
Quitar environment: del job en el workflow YAML. El deploy funcionará sin reglas de protección:
jobs:
deploy:
runs-on: ubuntu-latest
# Sin environment:
steps:
- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: '.'
exclude: |
.git/
agents/
.opencode/
# ... ignorar archivos no-desplegables
- uses: actions/deploy-pages@v4
Pitfall: Si el deploy tarda 2-5 segundos y termina en failure, es casi seguro un problema de environment protection rules, no de contenido.
Pitfall: POST /repos/.../pages con build_type: "workflow" requiere que el workflow use actions/deploy-pages@v4. Si el workflow no existe o no tiene este step, el deploy falla silenciosamente.
11. Deploy Pages para Repo EXISTENTE (caso más común)
Antes de crear nada, verificar si el repo ya existe.
Flujo seguro
# 1. CLONAR PRIMERO — si el clone falla, el repo no existe
git clone https://github.com/Ntizar/nombre-repo.git
# Si falla → repo no existe → ir a sección 12 (crear desde cero)
# Si funciona → repo existe → continuar
# 2. Verificar si Pages ya está activo
curl -s https://api.github.com/repos/Ntizar/nombre-repo/pages \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github.v3+json" | jq '.html_url'
# → "https://Ntizar.github.io/nombre-repo/" = ya activo
# → 404 = Pages no configurado → activar con POST
# 3. Si Pages ya está activo → VERIFICAR QUE SIRVE
curl -s -o /dev/null -w "%{http_code}" https://Ntizar.github.io/nombre-repo/
# → 200 = OK, no hacer nada más
# → 404 = Pages activo pero build fallido → verificar workflow, trigger, etc.
# 4. Si Pages no está activo → activar
curl -s -X POST https://api.github.com/repos/Ntizar/nombre-repo/pages \
-H "Authorization: token $TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-d '{"source":{"branch":"main","path":"/"}}'
# → 409 = ya activo (conflicto con estado previo)
Pitfalls críticos
- NUNCA crear un repo nuevo sin verificar primero que no existe. El nombre puede ser similar a otro existente (ej:
farospainvsfarosspain). Siempre intentar clonar primero. - Pages puede estar activo con build_type diferente (workflow vs legacy). Verificar con la API antes de intentar reactivar.
- El workflow de Pages puede existir pero no haber trigger. Si el repo tiene
.github/workflows/pages.ymlpero no se ha hecho push amain/master, el build nunca se ejecuta. - Branch name: Verificar si el repo usa
mainomasterantes de activar Pages. El workflow YAML indica cuál.
Checklist mental antes de actuar
- ¿Repo existe? →
git cloneprueba - ¿Pages activo? →
GET /repos/.../pages - ¿Sirve? →
curl -sI https://OWNER.github.io/REPO/ - Si todo OK → no hacer nada. Si algo falla → actuar.
12. Deploy Estático desde Cero (Repo Nuevo + Pages)
Cuando el usuario quiere crear un repositorio nuevo y desplegarlo en Pages desde cero (sin gh CLI):
Flujo completo
# 1. Crear directorio y repo local
mkdir -p /path/to/newproject && cd /path/to/newproject
git init
# ... crear archivos (index.html, README.md, etc.) ...
git add -A && git commit -m "feat: initial commit"
# 2. Crear repo en GitHub vía API
curl -s -X POST https://api.github.com/user/repos \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-d '{"name":"repo-name","description":"Descripción","private":false}'
# 3. Conectar remote y push
git remote add origin https://github.com/Ntizar/repo-name.git
git push -u origin master
# 4. Activar GitHub Pages
curl -s -X POST https://api.github.com/repos/Ntizar/repo-name/pages \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-d '{"source":{"branch":"master","path":"/"}}'
# 5. Verificar
sleep 15
curl -s -o /dev/null -w "%{http_code}" https://ntizar.github.io/repo-name/
# → 200 = OK
Pitfalls
- Token en URL: NO usar
https://TOKEN@github.com/...— los tokens tienen/,+,=que rompen parseo. Usargit remote add origin https://github.com/Ntizar/REPO.git(sin token) y dejar que git pida credenciales. - Pages tarda en construir: El estado puede ser "building" tras el POST. Esperar 15-30s y verificar con
curl -sI https://OWNER.github.io/REPO/. - Build con error null: El estado "built" con
error: {message: null}es normal en el build legacy de GitHub Pages — no bloquea el deploy. - index.html lowercase: GitHub Pages solo sirve
index.html(minúsculas).INDEX.html→ 404 en root URL.
Push con GITHUB_TOKEN (patrón que funciona)
El token de GitHub puede funcionar para la API REST pero fallar con git credential store o credential.helper normal. El patrón que funciona es:
source /hermes-home/.env
cd /path/to/repo
GIT_TERMINAL_PROMPT=0 git -c 'credential.helper=!f() { echo "username=oauth2"; echo "password='$GITHUB_TOKEN'"; }; f' push -u origin main
Por qué funciona: El credential.helper inline inyecta las credenciales directamente sin pasar por el sistema de credenciales de git. oauth2 como username es el formato que GitHub espera para tokens.
Pitfall: El primer push puede funcionar pero los siguientes fallan si el credential helper se resetea. Siempre usar el mismo patrón con -c 'credential.helper=...' en cada push.
Pitfall: Si el token es de instalación (no user token), puede funcionar con la API pero NO con git. Verificar con curl -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user — si devuelve 200, funciona para ambas cosas.
13. Branch Merge Selectivo — Fusión Inteligente de Dos Ramas
Ver referencia: references/branch-merge-selectivo-mastermind.md para el caso completo.
Cuando dos ramas tienen fortalezas complementarias (una con mejor diseño, otra con contenido más actualizado), el git merge directo no sirve. Patrón:
Resumen rápido
# 1. Inventario
git ls-tree -r --name-only master | sort > /tmp/m.txt
git ls-tree -r --name-only main | sort > /tmp/mn.txt
comm -23 /tmp/m.txt /tmp/mn.txt # solo en master
comm -13 /tmp/m.txt /tmp/mn.txt # solo en main
# 2. Clasificar por archivo: ¿master, main, o fusión manual?
# 3. Ejecutar fusión manual (reemplazos + limpieza)
# 4. Verificar: search_files('obsidian|opencode', path='.')
# 5. Actualizar GitHub description vía API REST
Decisiones típicas por archivo
| Archivo | Decisión | Razón |
|---|---|---|
README.md |
Fusión manual | Diseño de master + contenido de main |
index.html |
Fusión manual | Diseño de master + limpiar legacy |
SOUL.md, AGENTS.md, CHANGELOG.md |
✅ main | Solo existen en la versión actual |
| Archivos únicos de master | mover a legacy/ o eliminar según relevancia |
Fallos comunes del merge automático
git mergecon--strategy-option=theirssolo funciona si no hay cambios en el working treeAlready up to datesi main ya absorbió master via rebase → hay que hacer fusión manual- Archivos que cambian de nombre entre ramas (e.g.
agents/→legacy/agents/) → el merge no detecta la relación
Pitfalls específicos
- NUNCA eliminar branches sin preguntar — el usuario puede preferir el diseño de una rama aunque otra tenga el contenido más reciente
- GitHub description se actualiza vía
PATCH /repos/{owner}/{repo}con token, NO está en el repo - CDN Aurora → siempre
@latest, NUNCA@master - Referencias residuales → escanear con
search_filesnombres de plataforma antigua en TODOS los archivos activos (excluyendolegacy/)