tutoriales.com

Git Worktree: Gestiona Múltiples Versiones de tu Proyecto en Paralelo

Git Worktree es una potente característica de Git que te permite tener múltiples directorios de trabajo asociados al mismo repositorio. Esto facilita trabajar en diferentes ramas o versiones del código en paralelo, sin la necesidad de clonar el repositorio varias veces. Este tutorial te guiará a través de su configuración y uso para optimizar tu flujo de trabajo.

Intermedio10 min de lectura10 views
Reportar error

🚀 Introducción a Git Worktree

En el mundo del desarrollo de software, no es raro encontrarse con escenarios donde necesitamos trabajar en múltiples líneas de desarrollo simultáneamente. Quizás estés corrigiendo un bug urgente en una rama de producción, mientras que al mismo tiempo desarrollas una nueva característica en otra rama, y además, necesitas revisar el código de un compañero en una tercera. Tradicionalmente, esto implicaría clonar el repositorio varias veces en diferentes directorios, lo cual consume espacio en disco y puede ser engorroso de gestionar.

Aquí es donde Git Worktree brilla. Introducido en Git 2.5, git worktree nos permite adjuntar directorios de trabajo adicionales a un repositorio existente. Cada directorio de trabajo puede tener una rama diferente checked out, pero todos comparten el mismo repositorio .git central. Esto es una maravilla para la eficiencia y la organización.

💡 Consejo: Git Worktree es especialmente útil en monorepos o proyectos grandes donde clonar el repositorio repetidamente es ineficiente.

¿Por qué usar Git Worktree? 🤔

Las ventajas de usar git worktree son numerosas y pueden mejorar significativamente tu productividad:

  • Trabajo simultáneo en múltiples ramas: Desarrolla una característica, arregla un bug, y revisa un pull request al mismo tiempo, sin cambiar de rama constantemente en tu directorio principal. Cada worktree actúa como un entorno aislado para una rama específica.
  • Ahorro de espacio en disco: A diferencia de clonar el repositorio múltiples veces, worktree solo copia los archivos de trabajo y no el historial completo del repositorio para cada instancia. Todos los worktrees comparten el mismo objeto de base de datos de Git.
  • Cambio de contexto rápido: Evita el git stash y git pop constante cuando necesitas cambiar rápidamente entre tareas. Simplemente cambias a otro directorio de trabajo.
  • Pruebas en paralelo: Puedes ejecutar pruebas en una versión de tu código en un worktree mientras sigues desarrollando en otro.
  • Revisión de código simplificada: Abre el código de un compañero en un worktree separado para una revisión detallada sin ensuciar tu rama actual.

🛠️ Conceptos Clave de Git Worktree

Antes de sumergirnos en los comandos, es fundamental entender cómo funciona git worktree por debajo.

El Repositorio Principal y los Worktrees Adicionales

Cuando inicializas un repositorio Git (o lo clonas), se crea un directorio .git que contiene todo el historial, los objetos (commits, árboles, blobs) y las referencias (ramas, etiquetas). Este es tu repositorio bare o el corazón de tu proyecto. El directorio donde ejecutas git init o git clone es tu primer directorio de trabajo (o worktree).

git worktree te permite crear directorios adicionales que apuntan a este mismo repositorio .git subyacente. Cada uno de estos nuevos directorios es un worktree adicional, y en cada uno puedes tener una rama diferente checked out.

.git Repository (Central Database) main Worktree (main branch) Feature Worktree (feature-x branch) Bugfix Worktree (bugfix-y branch) Usa Usa Usa
🔥 Importante: Solo una rama puede estar checked out en un worktree a la vez. No puedes tener la misma rama checked out en dos worktrees diferentes.

Estructura de un Worktree

Dentro de cada worktree adicional, encontrarás los archivos de tu proyecto, igual que en tu worktree principal. Sin embargo, en lugar de un directorio .git completo, verás un archivo .git (¡sí, un archivo!) que contiene una referencia al verdadero directorio .git del repositorio principal. Por ejemplo:

# Contenido del archivo .git en un worktree adicional
gitdir: /path/to/main/repo/.git/worktrees/my-feature-worktree

Y dentro del directorio .git del repositorio principal, se crea un subdirectorio worktrees que contiene un directorio por cada worktree adicional. Este subdirectorio alberga la información específica de cada worktree, como la rama actual, HEAD, index, etc.

.git/
├── HEAD
├── config
├── description
├── hooks/
├── info/
├── objects/
├── refs/
└── worktrees/
    ├── my-feature-worktree/
    │   ├── HEAD
    │   ├── commondir
    │   ├── config
    │   ├── gitdir
    │   └── index
    └── another-bugfix-worktree/
        ├── HEAD
        ├── commondir
        ├── config
        ├── gitdir
        └── index

Esta estructura permite que cada worktree tenga su propio estado de HEAD e índice, pero comparta la base de datos de objetos (commits, etc.) del repositorio principal, ahorrando espacio y manteniendo la coherencia.


🚀 Uso Práctico de Git Worktree: Guía Paso a Paso

Vamos a ver cómo usar git worktree en escenarios reales. ¡Prepárate para optimizar tu flujo de trabajo!

1. Preparación del Repositorio Principal

Primero, asegúrate de tener un repositorio Git. Si no lo tienes, puedes crear uno de prueba:

# Crea un directorio para tu proyecto principal
mkdir my-project-root
cd my-project-root

# Inicializa un repositorio Git
git init

# Crea un archivo inicial y haz un commit
echo "Hola Worktree" > README.md
git add README.md
git commit -m "Initial commit"

# Crea algunas ramas para trabajar
git branch feature-x
git branch bugfix-y

Ahora tu repositorio principal está listo. Te encuentras en la rama main (o master).

2. Creando un Nuevo Worktree ➕

Para crear un nuevo worktree, usaremos el comando git worktree add. Necesitas especificar la ruta donde quieres que se cree el nuevo directorio de trabajo y, opcionalmente, la rama que quieres que tenga checked out.

Caso 1: Crear un Worktree con una Rama Existente

Vamos a crear un worktree para la rama feature-x.

git worktree add ../feature-x-worktree feature-x
  • ../feature-x-worktree: Es la ruta donde se creará el nuevo directorio de trabajo. Lo estamos creando fuera del directorio my-project-root para mantener las cosas ordenadas, pero podrías crearlo como un subdirectorio si lo prefieres.
  • feature-x: Es la rama existente que se pondrá checked out en este nuevo worktree.

Ahora, si navegas a ../feature-x-worktree, verás los archivos de tu proyecto, y git branch te mostrará que estás en feature-x.

cd ../feature-x-worktree
git branch
#   main
# * feature-x
#   bugfix-y

Caso 2: Crear un Worktree con una Nueva Rama

También puedes crear un worktree y, al mismo tiempo, crear una nueva rama y ponerla checked out allí. Esto es útil para empezar a trabajar en una característica completamente nueva.

git worktree add ../new-feature-worktree -b new-feature
  • -b new-feature: Indica a Git que cree una nueva rama llamada new-feature y la ponga checked out en este worktree. Si omites -b, Git intentará crear una nueva rama con el mismo nombre que el último componente de la ruta del worktree (en este caso, new-feature-worktree).
📌 Nota: Los worktrees creados sin especificar una rama se crearán en un estado 'HEAD detached' si el directorio ya existe o si no hay una rama implícita. Es buena práctica especificar siempre la rama.

Ahora tienes tres directorios de trabajo:

  • my-project-root (con main)
  • feature-x-worktree (con feature-x)
  • new-feature-worktree (con new-feature)

Puedes trabajar en cada uno de ellos de forma independiente, haciendo commits, stashes, etc., sin afectar a los otros. Los commits se añadirán al mismo repositorio .git central.

3. Listando Worktrees Existentes 📋

Para ver todos los worktrees asociados a tu repositorio, ejecuta:

git worktree list

La salida será similar a esta:

/path/to/my-project-root                   b8f7e1a [main]
/path/to/feature-x-worktree                1c3d5f7 [feature-x]
/path/to/new-feature-worktree              a2b4c6e [new-feature]

Esta lista muestra la ruta de cada worktree, el SHA del commit actual (HEAD) y la rama asociada.

4. Eliminando un Worktree 🗑️

Cuando hayas terminado con un worktree secundario, puedes eliminarlo. Asegúrate de que no tienes cambios pendientes (git status limpio) en el worktree que vas a eliminar, o que los has commiteado/stashed.

git worktree remove ../feature-x-worktree

Git eliminará el directorio de trabajo y limpiará las referencias internas en el directorio .git principal. Si el worktree contiene cambios no guardados, Git te advertirá y te impedirá eliminarlo. Puedes forzar la eliminación con -f:

git worktree remove -f ../feature-x-worktree
⚠️ Advertencia: Usar `-f` elimina los cambios sin confirmación. Asegúrate de que no necesitas esos cambios antes de forzar la eliminación.

También puedes eliminar el directorio manualmente después de git worktree remove si Git no lo hace por alguna razón, o si quieres moverlo:

git worktree prune # Elimina las entradas de worktrees que ya no existen en el sistema de archivos

git worktree prune es útil para limpiar referencias a worktrees que fueron eliminados manualmente sin usar git worktree remove.


🔄 Flujo de Trabajo con Git Worktree: Un Ejemplo Práctico

Imagina el siguiente escenario:

  1. Estás trabajando en la rama feature/login.
  2. De repente, surge un bug crítico en producción que necesita una solución inmediata en la rama hotfix/production.
  3. Además, tu compañero ha subido un nuevo pull request con la rama feature/dashboard que necesitas revisar.

Sin git worktree, tendrías que hacer git stash, git checkout hotfix/production, arreglar el bug, git commit, git checkout feature/login, git pop, git stash, git checkout feature/dashboard, etc. ¡Un caos!

Con git worktree, el flujo es mucho más limpio:

  1. Worktree principal: my-project-root (trabajando en feature/login)
# En my-project-root
git branch
# * feature/login
#   main
  1. Crear worktree para el hotfix:
# Desde my-project-root
git worktree add ../hotfix-worktree hotfix/production
Ahora abres otro terminal, navegas a `../hotfix-worktree`, arreglas el bug, haces tu commit y lo subes.
# En ../hotfix-worktree
# ... haces tus cambios ...
git add .
git commit -m "Fix critical production bug"
git push origin hotfix/production
  1. Crear worktree para la revisión:
# Desde my-project-root
git worktree add ../review-dashboard-worktree feature/dashboard
Abres un tercer terminal, vas a `../review-dashboard-worktree`, revisas el código, dejas tus comentarios y cierras.
# En ../review-dashboard-worktree
# ... revisas el código ...

Cuando termines con el hotfix y la revisión, simplemente eliminas los worktrees temporales:

# Desde my-project-root
git worktree remove ../hotfix-worktree
git worktree remove ../review-dashboard-worktree

¡Y vuelves a tu feature/login en my-project-root como si nada hubiera pasado! Sin stashes, sin cambios de contexto forzados.

Proyecto Principal (feature/login) Crear Worktree Eliminar Worktree Crear Worktree Eliminar Worktree Hotfix Worktree (hotfix/production) Review Worktree (feature/dashboard)
Ventajas y Desventajas de Git Worktree

Ventajas ✅

  • Eficiencia: No necesitas clonar múltiples veces el repositorio.
  • Rapidez: Cambio de contexto instantáneo entre ramas sin necesidad de stash.
  • Organización: Mantiene los entornos de trabajo limpios y separados.
  • Colaboración: Facilita la revisión de código y el trabajo en equipos grandes.

Desventajas ❌

  • Complejidad inicial: Puede parecer un concepto adicional que aprender para nuevos usuarios de Git.
  • Gestión de rutas: Hay que ser consciente de dónde se crean los worktrees para no perderlos de vista.
  • Una rama por worktree: No puedes tener la misma rama activa en dos worktrees. Si intentas hacer git worktree add con una rama ya activa, Git te lo impedirá.

💡 Consejos Avanzados y Buenas Prácticas

1. Ubicación de los Worktrees

Decide una convención para dónde almacenar tus worktrees. Una práctica común es crearlos como directorios hermanos de tu repositorio principal o en un subdirectorio dedicado.

# Estructura de ejemplo
~/projects/
├── my-project/
│   ├── .git/  (repositorio principal)
│   └── ... (main worktree)
├── my-project-feature-x/
│   └── ... (worktree para feature-x)
└── my-project-bugfix-y/
    └── ... (worktree para bugfix-y)

O dentro de un subdirectorio:

~/projects/my-project/
├── .git/
├── main-branch-code/
├── worktrees/
│   ├── feature-x-code/
│   └── bugfix-y-code/

Lo importante es la consistencia para que siempre sepas dónde buscar tus proyectos.

2. Manejo de Conflictos y Repositorios Remotos

Cada worktree puede interactuar con repositorios remotos de forma independiente. Puedes hacer git pull o git push desde cualquier worktree. Los conflictos de fusión se manejan como de costumbre dentro de cada worktree. Si el repositorio principal se actualiza (e.g., por un git fetch o git pull en main), los otros worktrees verán esos cambios cuando hagan su propio git pull o git merge.

3. Compartir Recursos entre Worktrees

Dado que todos los worktrees comparten el mismo repositorio .git subyacente, cualquier configuración a nivel de repositorio (ej. hooks, alias globales, configuraciones en .git/config) afectará a todos los worktrees. Esto es una ventaja, ya que mantienes una configuración centralizada.

4. Limpieza Periódica

Si eliminas manualmente un directorio de worktree sin usar git worktree remove, el registro interno de Git aún lo conocerá. Para limpiar estas referencias huérfanas, usa git worktree prune.

git worktree prune

5. Configuración del Repositorio Principal como "Bare" (Opcional)

Para algunos flujos de trabajo avanzados, especialmente en servidores o para repositorios compartidos, puede ser útil que el repositorio principal sea un repositorio bare (sin directorio de trabajo asociado). Esto se hace a menudo para evitar que se hagan cambios directamente en el directorio principal.

Puedes inicializar un repositorio bare así:

mkdir my-project.git
cd my-project.git
git init --bare

Luego, añadir worktrees a este repositorio bare:

git --git-dir=/path/to/my-project.git worktree add /path/to/my-project/main-worktree main

Esto es más común en escenarios donde el repositorio principal no es para el trabajo directo, sino como un punto central de donde se ramifican múltiples worktrees.

Worktree Mastery

🏁 Conclusión

Git Worktree es una característica increíblemente potente y subutilizada que puede transformar la forma en que interactúas con tus repositorios Git. Al permitirte trabajar en múltiples ramas simultáneamente sin la complejidad de clonaciones múltiples o el constante stash/pop, git worktree simplifica enormemente el cambio de contexto y aumenta tu eficiencia.

Al integrar git worktree en tu flujo de trabajo, no solo ahorrarás tiempo y espacio en disco, sino que también disfrutarás de una experiencia de desarrollo más fluida y organizada. ¡Anímate a probarlo y descubre cómo puede mejorar tu productividad!

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!