¿Para qué usaría git-worktree?

211

Leí la publicación de Github en git-worktree . Escriben:

Suponga que está trabajando en un repositorio Git en una rama llamada feature, cuando un usuario informa un error de alta urgencia master. Primero, crea un árbol de trabajo vinculado con una nueva rama, hotfixdesprotegido en relación con el maestro […] Puede corregir el error, aplicar una revisión y crear una solicitud de extracción.

Cuando estoy trabajando en una rama llamada característica y se informa de algún error de alta urgencia en el maestro, generalmente guardo todo lo que estoy trabajando y creo una nueva rama. Cuando termine, puedo seguir trabajando. Este es un modelo muy simple, he estado trabajando así durante años.

Por otro lado, usar git-worktree tiene sus propias limitaciones:

Por ejemplo, no está permitido tener la misma rama desprotegida en dos árboles de trabajo vinculados al mismo tiempo, porque eso permitiría que los cambios comprometidos en un árbol de trabajo desactiven la otra.

¿Por qué elegiría un flujo de trabajo más complicado para un problema que ya se ha resuelto?

¿Hay algo sobre git-worktreeeso que no se pueda hacer de antemano y que justifique esta característica completamente nueva y compleja?

awendt
fuente
12
Una cosa que no puede esconder son los caminos no fusionados, después de una fusión o rebase con conflictos.
chirlu
11
Si trabaja con un lenguaje compilado, el almacenamiento significa que tendrá que volver a compilar todo cuando esté descomprimiendo.
mb14
Tenemos varios productos diferentes basados ​​en el mismo código fuente (300 MB), y planeo combinarlos todos en un gran repositorio y usar worktree para mantener cada producto desprotegido en una carpeta diferente, en lugar de tener un montón de clones que no permanecen sincronizados
endolito

Respuestas:

197

Para mí, git worktree es la mayor mejora desde hace mucho tiempo. Estoy trabajando en el desarrollo de software empresarial. Allí, es muy común que tenga que mantener versiones antiguas como la que lanzó hace 3 años. Por supuesto, tiene una rama para cada versión para que pueda cambiar fácilmente a ella y corregir un error. Sin embargo, el cambio es costoso, porque mientras tanto reestructuró completamente el repositorio y quizás construyó el sistema. Si cambia, su IDE se volverá loco tratando de adaptar la configuración del proyecto.

Con worktree, puede evitar esa constante reconfiguración. Verifique esas ramas viejas en carpetas separadas usando worktree. Para cada sucursal, tienes un proyecto IDE independiente.

Por supuesto, esto podría haberse hecho en el pasado clonando el repositorio varias veces y este ha sido mi enfoque hasta ahora. Sin embargo, eso también significó malgastar el espacio en el disco duro y peor aún necesitar recuperar los mismos cambios del repositorio varias veces.

Sebi
fuente
44
No tuvo que obtener los mismos cambios del repositorio varias veces. Podría haber simplemente copiado el directorio .git del primer clon.
misiu_mp
1
@ jdk1.0 perdón por la confusión, el comentario fue dirigido a misiu_mp
mxttie
2
Como alguien que ha usado 2-3 repositorios altamente replicados para poder construir una rama de características mientras desarrollo en otra, tenía cada repositorio local como control remoto de los demás y estoy completamente de acuerdo con las caracterizaciones de Sebi de las desventajas (¡mucha búsqueda y empuje! ) Además, una vez que me cambio a worktree, deduzco que ya no tendré que preocuparme por la divergencia de sucursales locales con el mismo nombre (lo que ocurre aproximadamente una vez cada 6-10 meses, ya que me interrumpen varias veces durante un período de días y termino trabajando la misma rama de función de múltiples repositorios, pero olvide sincronizarlos de nuevo ...)
sabio
3
@iheanyi - (1). Es más rápido si el IDE mantiene archivos de datos externos (como bases de datos de indexación) asociados con un directorio determinado. Si agota el contenido en el mismo directorio, eso normalmente invalidará cualquier caché de datos IDE y tendrá que volver a indexar.
Steve Hollasch
55
@iheanyi - (2) Con el tiempo, la historia de todo crecerá mucho más que los archivos del árbol de trabajo en cualquier punto dado. La historia de todo == el .gitdirectorio. Con muchos clones locales del flujo ascendente, tiene muchas copias locales de la misma base de datos, ya que cada clon tiene su propia .gitbase de datos. Con muchos árboles de trabajo locales, cada árbol usa la misma .gitbase de datos. Sí, si tiene clones locales de su árbol de trabajo local, Git enlazará gran parte del contenido de .git, pero no en Windows.
Steve Hollasch
71

Puedo ver algunos usos para esto.

Si tiene un conjunto de pruebas que se ejecuta durante mucho tiempo, imagine horas y lo inicia, efectivamente bloquea esa copia de trabajo hasta que se completen las pruebas. Cambiar ramas durante esas pruebas las rompería de una manera que sería difícil de entender.

Entonces git-worktree, podría tener una segunda idea lanzada para otra sucursal que trabaje allí.

Además, cuando cambio a otra rama para hacer una investigación rápida, mi IDE piensa que muchos archivos cambiaron repentinamente e indexarán todos esos cambios, solo para tener que volver a indexarlos nuevamente cuando vuelva a cambiar.

Un tercer caso de uso sería hacer una comparación de archivos usando otras herramientas que git-diff, como es normal diff, entre dos directorios en lugar de dos ramas.

Andreas Wederbrand
fuente
66
¿No git clonefuncionaría igual de bien para todo esto?
2015
12
Pero clonar un gran repositorio desde el control remoto puede llevar mucho tiempo. Estoy trabajando contra un repositorio que toma varios minutos para clonar. Supongo que podrías hacerlo git clone --reference. Además, la administración de todas las demás ramas se realizará solo una vez en lugar de una vez por directorio de trabajo.
Andreas Wederbrand
66
No clones desde el control remoto, clona desde tu local. No entiendo el problema de la gestión de sucursales, ¿puede aclararlo?
jthill
14
Traté de usar clones, y realmente hay un problema de administración. En lugar de un solo conjunto de ramas, tengo un conjunto de clones, que no puedo ver todos juntos en una sola interfaz de usuario. Si necesito elegir algunos cambios, tengo que buscarlos o empujarlos. Agrega pasos adicionales a todas las acciones. Todo es factible, pero siempre hay algo de fricción.
max630
2
Y cuando se trata de configurar una copia de seguridad, el repositorio único es mucho más fácil.
max630
64

Un uso obvio es comparar simultáneamente el comportamiento (no fuente) de diferentes versiones, por ejemplo, diferentes versiones de un sitio web o simplemente una página web.

Probé esto localmente.

  • crear un directorio page1.

  • dentro crea el directorio srcy git initlo.

  • en srccrear page1.htmlcon un poco de contenido y comprometerlo.

  • $ git branch ver0

  • $ git worktree add ../V0 ver0

  • en srcmaster agregue más texto page1.htmly confírmelo.

  • $ git branch sty1

  • edite page1.htmlen la sty1rama (agregue un estilo CSS distintivo) y agregue commit.

  • $ git worktree add ../S1 sty1

Ahora puede usar un navegador web para abrir y ver estas 3 versiones simultáneamente:

  • ..\page1\src\page1.html // lo que sea que git tenga como actual

  • ..\page1\V0\page1.html // la versión inicial

  • ..\page1\S1\page1.html // la versión de estilo experimental

RodMcGuire
fuente
2
No veo cómo esto explica el beneficio de usar worktree para este propósito sobre un clon.
iheanyi
@iheanyi Se podría decir lo mismo sobre branch; la respuesta también es la misma: es más liviana y está diseñada para el trabajo.
OJFord
1
@OJFord ese es el punto. Esta respuesta no me explica qué hace Worktree que es diferente. Obviamente no es un alias para rama o clon, pero el efecto que estoy viendo aquí parece ser el mismo. No veo cómo esto sea más liviano que solo usar una rama o un clon.
iheanyi
@iheanyi Es diferente a usar una rama (no puede usar ramas solo para obtener múltiples estados de worktree a la vez) y un peso más ligero que un segundo (.., enésimo) clon. Lo que quise decir es que también se podría decir de la rama "por qué no solo clonar y hacer los cambios", sino que varias ramas en un único repositorio son una forma más liviana y más fácil de lograr ese comportamiento.
OJFord
@OJFord No creo que esto resuelva mi confusión con worktree. Permítanme decirlo de esta manera, ya sea que usen rama o clon u otra cosa, el objetivo final del proceso descrito aquí es comparar tres versiones diferentes de algo simultáneamente. Según lo que hay en la respuesta, no entiendo por qué usaría worktree sobre alguna alternativa. La respuesta no explica qué está haciendo worktree que las alternativas no. Usted afirma que algo es liviano (o más liviano) pero no veo cómo worktree hace que las ramas sean menos "pesadas".
iheanyi
29
  1. Hay razones legítimas por las que puede querer / necesitar múltiples worktrees en el sistema de archivos a la vez.

    • manipular los archivos desprotegidos mientras necesita realizar cambios en otro lugar (por ejemplo, compilar / probar)

    • diferenciar los archivos a través de herramientas diff normales

    • Durante los conflictos de fusión, a menudo quiero navegar a través del código fuente ya que está en el lado fuente mientras resuelvo conflictos en los archivos.

    • Si necesita cambiar mucho de un lado a otro, hay que perder el tiempo al pagar y volver a verificar que no tiene que ver con varios árboles de trabajo.

    • El costo mental del cambio de contexto mental entre ramas a través de git stashing no es realmente medible. Algunas personas encuentran que existe un costo mental para el almacenamiento que no existe simplemente abriendo archivos desde un directorio diferente.

  2. Algunas personas preguntan "por qué no hacer múltiples clones locales". Es cierto que con el indicador "--local" no tiene que preocuparse por el uso de espacio extra en el disco. Esto (o ideas similares) es lo que he hecho hasta este momento. Las ventajas funcionales de los árboles de trabajo vinculados sobre los clones locales son:

    1. Con los clones locales, sus árboles de trabajo adicionales (que están en los clones locales) simplemente no tienen acceso a las ramas de origen o ascendentes. El 'origen' en el clon no será el mismo que el 'origen' en el primer clon.

      • Correr git log @{u}..o git diff origin/feature/other-featurepuede ser muy útil y esto ya no es posible o más difícil. Estas ideas son técnicamente posibles con clones locales a través de una variedad de soluciones, pero cada solución que pueda hacer se hace mejor y / o más simple a través de vías de trabajo vinculadas.
    2. Puede compartir referencias entre árboles de trabajo. Si desea comparar o tomar prestados cambios de otra sucursal local, ahora puede hacerlo.

Alexander Bird
fuente
11
También puede enumerar todos los árboles de trabajo con un solo comando, con clones que necesita hacer un seguimiento de ellos.
Ian Ringrose
hmm A partir de git 2.7.0, ese parece ser el caso. Bueno saber.
Alexander Bird
9

tl; dr: cada vez que desee que se revisen dos árboles de trabajo al mismo tiempo por cualquier razón, git-worktreees una forma rápida y eficiente de hacerlo.

Si crea otro árbol de trabajo, la mayoría de las partes del repositorio (es decir .git) se compartirán, lo que significa que si crea una rama o obtiene datos mientras está en un árbol de trabajo, también será accesible desde cualquier otro árbol de trabajo que tenga. Supongamos que desea ejecutar su conjunto de pruebas en una sucursal sin tener que empujarlo a algún lugar para clonarlo, y desea evitar la molestia de clonar su repositorio localmente, usar git-worktreees una buena manera de crear solo un nuevo pago de algún estado en un lugar separado, ya sea temporal o permanentemente. Al igual que con un clon, todo lo que necesita hacer cuando haya terminado es eliminarlo, y la referencia a él será recolectada de basura después de un tiempo.

jsageryd
fuente
2
Los médicos dicen que no puede tener la misma rama en ambas copias de trabajo, lo cual es una limitación seria. Con Mercurial, funcionó solo con pequeños problemas.
hypersw
Seguro que puede. La página del manual dice cómo; busque --force. Pero es inconveniente si actualiza la sucursal en un lugar y espera trabajar en ella en otro, ya que el árbol de trabajo no se actualiza.
jsageryd
Sí, las sucursales en Mercurial son un concepto más transparente en este aspecto. ¿Cómo aparecen las ramas de un árbol de trabajo en el otro? ¿De la misma manera que múltiples enlaces ascendentes? Mis primeros experimentos con árboles de trabajo, con ejecutar fetch en ambos, terminaron con dos (!) Punteros diferentes (!) Nombrados origin/master.
hypersw
Un árbol de trabajo es (como su nombre lo indica) solo un árbol de trabajo, con algunas características adicionales agregadas; El repositorio se comparte entre todos los árboles de trabajo. La única diferencia entre dos worktrees es que la rama desprotegida puede ser (y para flujos de trabajo sanos, es) diferente. Es posible comprometerse en un árbol de trabajo separado, por lo que también tiene su propio índice (también conocido como área de preparación) para que funcione. El .gitarchivo en el árbol de trabajo separado es un archivo de texto que contiene la ruta a su configuración, que reside en el repositorio original.
jsageryd
2
@WilsonF: git checkout --ignore-other-worktrees <branch> git-scm.com/docs/git-checkout/…
jsageryd
7

Originalmente me topé con esta pregunta después de preguntarme para qué podrían usarse estos elegantes árboles de trabajo. Desde entonces los he integrado en mi flujo de trabajo y, a pesar de mi escepticismo inicial, he llegado a encontrarlos bastante útiles.

Trabajo en una base de código bastante grande, que lleva bastante tiempo compilar. Por lo general, tengo la rama de desarrollo actual en mi máquina junto con la rama de características en la que estoy trabajando actualmente más la rama maestra, que representa el estado actual del sistema en vivo.

Obviamente, uno de los mayores beneficios para mí es que no tengo que volver a compilar todo cada vez que cambio de sucursales (es decir, árboles de trabajo). Un buen efecto secundario es que puedo ir al árbol de trabajo de desarrollo, hacer cosas allí, cambiar el directorio al árbol de trabajo de mi rama de características actual y luego volver a crearlo sin tener que tirar primero.

rethab
fuente
4

Tengo uno bastante inusual: estoy desarrollando Windows y Linux en la misma máquina . Tengo un VirtualBox ejecutando Linux dentro de mi caja de Windows. VirtualBox monta algunos directorios de Windows y los usa directamente dentro de la máquina Linux. Esto me permite usar Windows para administrar archivos pero construir dentro de Linux. Este es un proyecto multiplataforma, por lo que se basa en Windows y Linux desde la misma estructura de directorios.

El problema es que los sistemas de compilación de Linux y Windows chocan entre sí cuando se usan en el mismo directorio; Hay algunos pasos de compilación complicados para descargar bibliotecas, etc., que usan los mismos nombres de directorio. La versión de Windows del sistema de compilación descarga las bibliotecas específicas de Windows, y la versión de Linux del sistema de compilación descarga las bibliotecas específicas de Linux.

En un mundo ideal, el sistema de compilación se modificaría para que Windows y Linux puedan coexistir dentro del directorio, pero por ahora, el problema se está abordando con worktrees. La carpeta "Linux" puede generar artefactos de compilación específicos de Linux, y la carpeta "Windows" puede generar artefactos de compilación específicos de Windows. Si bien esta no es una solución ideal, hace una buena pausa mientras espera que se solucionen los errores del sistema de compilación.

Es cierto que worktree no fue diseñado para esto; Tengo que mantener la versión de Windows y la versión de Linux en ramas separadas, aunque realmente prefiero que estén en la misma rama. Aún así, está haciendo el trabajo, y es un caso poco convencional de worktree que salva el día.

AHelps
fuente
+1 Esto parece una solución muy efectiva para Make no hacer directorios de salida de compilación por configuración de forma nativa. Tengo una configuración similar de VMware Workstation con invitados Ubuntu y macOS.
Tanz87
1

En un nuevo proyecto para mí, he creado una función. Pero algunas especificaciones fallaron. Para comparar resultados con master, creé un work-treerepositorio. Comparé los resultados paso a paso en el código de ejecución, hasta entender qué salió mal.

itsnikolay
fuente
Sin embargo, ¿cómo hace un árbol de trabajo para que esto sea más fácil que un clon? La pregunta no es pedir preferencias personales, sino diferencias concretas.
Inspeccionable el
1

Estoy usando git worktreepara el desarrollo de aprendizaje automático.

Tengo un código funcional principal y luego quiero dividir ramas de diferentes experimentos (diferentes algoritmos e hiperparámetros diferentes). git worktreeme permite integrar dvc junto con diferentes versiones de mi código especializadas para diferentes algoritmos. Después de ejecutar todos los trabajos de capacitación, evalúo las métricas finales y las combino para dominar la mejor rama / modelo.

Ricardo MS
fuente