El problema habitual del desarrollo en paralelo no es crear otra rama. Git hace esa parte trivial. El problema es asegurarte de que lo que estás probando sea realmente la rama que acabas de modificar, que el servicio se esté ejecutando desde el directorio correcto y que el commit final no arrastre archivos que no tienen nada que ver.

Con el tiempo acabé usando un patrón mucho más limpio: mantener estable el directorio principal del repositorio y utilizar git worktree para dar a cada rama de feature su propio directorio de trabajo aislado. Desde que lo hago de forma consistente, ejecutar varias features en paralelo en la misma máquina se ha vuelto mucho menos propenso a errores.

Si buscas desarrollo paralelo con ramas Git, un workflow con Git worktree o un proceso estándar para ramas aisladas, este artículo trata exactamente de eso.

Por qué dejé de depender del cambio constante de ramas

El problema central no es crear ramas. Es la contaminación.

En un único directorio de repositorio, los ciclos repetidos de checkout tienden a crear siempre las mismas clases de problemas:

  • crees que estás probando una nueva feature, pero el servicio en ejecución sigue viniendo de otro directorio
  • los artefactos de build de una feature se filtran a otra rama
  • git add . recoge silenciosamente archivos que nunca deberían commitearse
  • los bugfixes y el trabajo de features empiezan a compartir el mismo workspace desordenado

Eso es precisamente lo que Git worktree resuelve muy bien. No solo te ayuda a crear una rama más rápido. Le da a cada rama un lugar físicamente separado donde vivir.

Las reglas de directorio que mantengo fijas

Para que el workflow sea aburrido en el buen sentido, convierto unas pocas convenciones en reglas no negociables:

  • repositorio principal: /Users/kuangyongjie/charting_library
  • raíz de worktrees: /Users/kuangyongjie/worktrees
  • formato de rama: codex/<feature-name>
  • rama principal: master

El repositorio principal se reserva para estabilidad y merges, mientras que el trabajo de features ocurre en rutas como:

/Users/kuangyongjie/worktrees/hotspot-ff

Parece un detalle pequeño, pero cambia mucho. Cuando la propia ruta ya indica dónde estás, es bastante más difícil confundir el repo principal con un workspace de feature.

El flujo estándar es corto, pero cada paso importa

Primero asegúrate de que existe la raíz de worktrees:

mkdir -p /Users/kuangyongjie/worktrees

Después crea un worktree y una nueva rama desde el repositorio principal:

REPO=/Users/kuangyongjie/charting_library
WT=/Users/kuangyongjie/worktrees/<feature-name>
BRANCH=codex/<feature-name>
BASE=master

# If the remote is available, update master first
# git -C "$REPO" pull --rebase central "$BASE"

git -C "$REPO" worktree add "$WT" -b "$BRANCH" "$BASE"
cd "$WT"
git branch --show-current

La salida esperada es:

codex/<feature-name>

Esta confirmación importa. A partir de ahí, desarrollo, builds y validación local deberían permanecer dentro de "$WT".

Haz todo el desarrollo y las pruebas dentro del directorio de la rama

Una vez creado el worktree, intento ser estricto: construir y ejecutar únicamente desde el directorio de esa rama.

Por ejemplo, si el frontend vive en una carpeta interna:

cd "$WT/trendradar-service/trendradar-web"
npm run build
# production obfuscated build
# npm run build:multi-layer

Una de las falsas pistas de debugging más habituales es: “he cambiado el código, pero la página sigue viéndose vieja”. Muchas veces el código está bien. El proceso simplemente se está ejecutando desde otro sitio.

Cuando algo parece desactualizado, reviso primero el cwd del proceso:

lsof -nP -iTCP:<port> | sed -n '1,5p'
ps -p <pid> -o pid,ppid,command
lsof -p <pid> | rg "cwd"

Lo que quieres confirmar es que el directorio de trabajo actual apunte realmente a:

/Users/kuangyongjie/worktrees/<feature-name>/...

Si no es así, probablemente estás probando la rama equivocada, independientemente de lo que diga Git.

Casi nunca utilizo git add . en este flujo

Aquí prefiero ser deliberadamente conservador.

Con worktrees en paralelo, stageo solo los archivos objetivo en vez de recoger todo el directorio. Es demasiado fácil commitear por accidente restos de runtime, snapshots locales, cachés o archivos generados.

Los sospechosos habituales son:

  • __pycache__
  • *.db
  • snapshot_*
  • .DS_Store

Mi patrón normal se parece más a esto:

cd "$WT"
git add <file1> <file2> <file3>
git status --short
git commit -m "feat/fix: <summary>"

Ese git status --short extra es pequeño, pero detecta bastante ruido.

Haz merge de vuelta solo desde el repositorio principal

Cuando la feature está lista, no hago el merge desde dentro del worktree. Vuelvo al repositorio principal y hago merge allí:

cd /Users/kuangyongjie/charting_library
git branch --show-current   # must be master

# If the remote is available, update first
# git pull --rebase central master

git merge --no-ff codex/<feature-name>

Lo importante no es tanto --no-ff como verificar que realmente estés en la rama principal y en el directorio principal antes de hacer merge.

Si aparece:

MERGE_HEAD exists

normalmente significa que el merge anterior no terminó correctamente. En ese caso:

git merge --abort

y después repite la secuencia pull/merge.

Si también necesitas hacer push:

cd /Users/kuangyongjie/charting_library
git push <remote> master

Un detalle práctico: en esta máquina el remote habitual suele llamarse central, no origin. Eso es un detalle del entorno, no un problema de Git worktree.

Cuándo uso fast-forward en lugar de dejar un merge commit

A veces la necesidad cambia: probar dentro de un directorio de rama aislado y después volver a main sin crear un merge commit.

Ahí tiene sentido un flujo de fast-forward. Por ejemplo:

cd /Users/kuangyongjie/charting_library
git checkout master
git pull --rebase central master

git worktree add /Users/kuangyongjie/worktrees/hotspot-ff -b codex/hotspot-ff master

Después ejecuta el servicio únicamente desde ese worktree:

cd /Users/kuangyongjie/worktrees/hotspot-ff/trendradar-service
./venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 9544

Y desde otra terminal verifica el cwd:

lsof -nP -iTCP:9544 -sTCP:LISTEN
ps -p <PID> -o pid,ppid,command
lsof -a -p <PID> -d cwd -Fn

Vale la pena repetir esta comprobación porque decir “la rama pasó las pruebas” sirve de poco si el proceso nunca se ejecutó desde el directorio correcto.

Las reglas que ahora considero obligatorias

Si vas a utilizar worktrees a largo plazo, mantendría al menos estas reglas:

  • una feature por directorio de worktree
  • una tarea o una conversación por worktree
  • ejecutar git branch --show-current antes de empezar
  • ejecutar git status --short antes de cada commit
  • hacer merge únicamente desde el repositorio principal master

Ninguna regla es complicada. Precisamente por eso funcionan.

Problemas habituales

La página local sigue mostrando el resultado antiguo

No asumas de inmediato que el cambio de código falló.

Primero comprueba que el cwd del proceso esté dentro del worktree objetivo. Después verifica que realmente reconstruiste los assets desde ese directorio de rama.

fatal: 'origin' does not appear to be a git repository

Normalmente el nombre del remote es incorrecto. Ejecuta:

git remote -v

y haz push al remote real. En este entorno suele ser central.

MERGE_HEAD exists

Normalmente el último merge quedó sin terminar. Ejecuta:

git merge --abort

y reinicia el flujo de merge.

Solo cambié archivos de frontend. ¿Tengo que reiniciar el backend?

Normalmente no. Si los assets estáticos se reconstruyeron y desplegaron correctamente, suele bastar con refrescar la caché.