ver tipos tag qué modificados log existen etiquetas crear archivos git

tipos - ¿Múltiples directorios de trabajo con Git?



tipos de etiquetas en git (4)

Encontré esta pregunta esperando una solución que no encontré aquí. Así que ahora que encontré lo que necesitaba, decidí publicarlo aquí para otros.

Advertencia: probablemente no sea una buena solución si necesita editar varias ramas simultáneamente, como los estados OP. Es por tener varias sucursales activadas simultáneamente que no tiene intención de editar. (Múltiples directorios de trabajo respaldados por una carpeta .git).

Hubo algunas cosas que aprendí desde que llegué a esta pregunta la primera vez:

  1. Qué es un " repositorio simple ". Es esencialmente el contenido del directorio .git , sin estar ubicado en un árbol de trabajo.

  2. El hecho de que puede especificar la ubicación del repositorio que está utilizando (la ubicación de su .git dir) en la línea de comandos con la opción git --git-dir=

  3. El hecho de que puede especificar la ubicación de su copia de trabajo con --work-tree=

  4. Qué es un "repo espejo".

Esta última es una distinción bastante importante. Realmente no quiero trabajar en el repositorio, solo necesito tener copias de diferentes sucursales y / o etiquetas desprotegidas simultáneamente. De hecho, necesito garantizar que las sucursales no terminen siendo diferentes de las sucursales de mi control remoto. Así que un espejo es perfecto para mí.

Así que para mi caso de uso, obtuve lo que necesitaba haciendo:

git clone --mirror <remoteurl> <localgitdir> # Where localgitdir doesn''t exist yet mkdir firstcopy mkdir secondcopy git --git-dir=<localgitdir> --work-tree=firstcopy checkout -f branch1 git --git-dir=<localgitdir> --work-tree=secondcopy checkout -f branch2

La gran advertencia sobre esto es que no hay una CABEZA separada para las dos copias. Entonces, después de lo anterior, ejecutar git --git-dir=<localgitdir> --work-tree=firstcopy status mostrará todas las diferencias de branch2 a branch1 como cambios no comprometidos, porque HEAD apunta a branch2. (Es por eso que utilizo la opción -f para realizar el checkout , porque no planeo realizar ningún cambio localmente. Puedo verificar cualquier etiqueta o rama para cualquier árbol de trabajo, siempre que use la opción -f . )

Para mi caso de uso de tener múltiples pagos coexistiendo en la misma computadora sin necesidad de editarlos , esto funciona perfectamente. No sé si hay alguna forma de tener múltiples HEAD para los múltiples árboles de trabajo sin un script como el que se trata en las otras respuestas, pero espero que esto sea útil para otra persona de todos modos.

No estoy seguro de si esto es algo respaldado por Git, pero en teoría parece que debería funcionar para mí.

Mi flujo de trabajo a menudo involucra mi edición de archivos en múltiples ramas simultáneamente. En otras palabras, a menudo quiero abrir algunos archivos en una rama mientras edito el contenido de otro archivo en otra rama.

Mi solución típica para esto es hacer dos pagos, pero es una pena que no pueda compartir sucursales y referencias entre ellos. Lo que me gustaría es tener dos directorios de trabajo gestionados por la misma carpeta .git.

Soy consciente de las soluciones locales de clonación de git (el valor predeterminado, que es vincular los objetos compartidos, y la opción --compartida, que configura un almacén de objetos alternativo con el repositorio original), pero estas soluciones solo reducen el uso del espacio en disco. , y especialmente en el caso de --shared, parecen estar plagadas de peligros.

¿Hay alguna forma de usar una carpeta .git y tener dos directorios de trabajo respaldados por ella? ¿O está Git codificado para tener un solo directorio activo en cualquier momento?


Git 2.5 propone, desde julio de 2015, un reemplazo para contrib/workdir/git-new-workdir : git worktree

Ver commit 68a2e6a de Junio ​​C Hamano ( gitster ) .

La nota de lanzamiento menciona :

Un reemplazo para contrib/workdir/git-new-workdir que no se basa en enlaces simbólicos y hace que compartir objetos y referencias sea más seguro al hacer que el prestatario y los prestatarios se conozcan entre sí.

Ver commit 799767cc9 (Git 2.5rc2)

Eso significa que ahora puede hacer un git worktree add <path> [<branch>]

Cree <path> y extraiga <branch> en él. El nuevo directorio de trabajo está vinculado al repositorio actual, compartiendo todo excepto los archivos específicos del directorio de trabajo, como HEAD, índice, etc. La sección git worktree agrega:

Un repositorio de git puede admitir múltiples árboles de trabajo , lo que le permite revisar más de una rama a la vez.
Con git worktree add , se asocia un nuevo árbol de trabajo con el repositorio.

Este nuevo árbol de trabajo se denomina "árbol de trabajo vinculado" en oposición al "árbol de trabajo principal" preparado por " git init " o " git clone " .
Un repositorio tiene un árbol de trabajo principal (si no es un repositorio simple) y cero o más árboles de trabajo vinculados.

detalles:

Cada árbol de trabajo vinculado tiene un subdirectorio privado en el directorio $GIT_DIR/worktrees del repositorio.
El nombre del subdirectorio privado suele ser el nombre base de la ruta del árbol de trabajo vinculado, posiblemente adjuntado con un número para hacerlo único.
Por ejemplo, cuando $GIT_DIR=/path/main/.git el comando git worktree add /path/other/test-next next crea:

  • el árbol de trabajo vinculado en /path/other/test-next y
  • también crea un $GIT_DIR/worktrees/test-next (o $GIT_DIR/worktrees/test-next1 si test-next ya está en uso).

Dentro de un árbol de trabajo vinculado:

  • $GIT_DIR está configurado para apuntar a este directorio privado (por ejemplo, /path/main/.git/worktrees/test-next en el ejemplo) y
  • $GIT_COMMON_DIR está configurado para apuntar a $GIT_DIR del árbol de trabajo principal (por ejemplo, /path/main/.git ).

Estas configuraciones se realizan en un archivo .git ubicado en el directorio superior del árbol de trabajo vinculado.

Cuando haya terminado con un árbol de trabajo vinculado, simplemente puede eliminarlo.
Los archivos administrativos del árbol de trabajo en el repositorio finalmente se eliminarán automáticamente (vea gc.pruneworktreesexpire en git config ), o puede ejecutar git worktree prune en el árbol de trabajo principal o vinculado para limpiar cualquier archivo administrativo obsoleto.

Advertencia: todavía hay una git worktree "BUGS" de git worktree a tener en cuenta.

El soporte para submodules es incompleto .
NO se recomienda realizar varias verificaciones de un superproyecto.

Nota: con git 2.7rc1 (noviembre de 2015) puede listar sus áreas de trabajo.
Ver commit bb9c03b , commit 92718b7 , commit 5193490 , commit 1ceb7f9 , commit 1ceb7f9 , commit 5193490 , commit 1ceb7f9 , commit 1ceb7f9 (08 Oct 2015), commit 92718b7 , commit 519349 , commit 1ceb7f9 , commit 1ceb7pcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpcpv : eq . commit 1ceb7f9 (08 oct 2015), commit 1ceb7f9 (08 oct 2015) y commit ac6c561 (02 oct 2015) por Michael Rappazzo ( rappazzo ) .
(Fusionada por Junio ​​C Hamano - gitster - in commit a46dcfb , 26 de octubre de 2015)

worktree : agregar comando '' list ''

'' git worktree list '' itera a través de la lista de worktree, y muestra los detalles del worktree, incluyendo la ruta al worktree, la revisión y rama actualmente verificada, y si el árbol de trabajo está vacío.

$ git worktree list /path/to/bare-source (bare) /path/to/linked-worktree abcd1234 [master] /path/to/other-linked-worktree 1234abc (detached HEAD)

También hay opción de formato de porcelana disponible.

El formato de porcelana tiene una línea por atributo.

  • Los atributos se enumeran con una etiqueta y un valor separados por un solo espacio.
  • Los atributos booleanos (como ''bare'' y ''desligados'') se listan solo como una etiqueta, y solo están presentes si y solo si el valor es verdadero.
  • Una línea vacía indica el final de un árbol de trabajo.

Por ejemplo:

$ git worktree list --porcelain worktree /path/to/bare-source bare worktree /path/to/linked-worktree HEAD abcd1234abcd1234abcd1234abcd1234abcd1234 branch refs/heads/master worktree /path/to/other-linked-worktree HEAD 1234abc1234abc1234abc1234abc1234abc1234a detached

Nota: si MOVE una carpeta de worktree, necesita actualizar manualmente el archivo gitdir .

Consulte commit 618244e (22 de enero de 2016) y commit d4cddd6 (18 de enero de 2016) por Nguyễn Thái Ngọc Duy ( pclouds ) .
Ayudado por: Eric Sunshine ( sunshineco ) .
(Fusionada por Junio ​​C Hamano - gitster - in commit d0a1cbc , 10 de febrero de 2016)

El nuevo documento en git 2.8 (marzo de 2016) incluirá:

Si mueve un árbol de trabajo vinculado, necesita actualizar el archivo '' gitdir '' en el directorio de la entrada.
Por ejemplo, si un árbol de trabajo vinculado se mueve a /newpath/test-next y su archivo .git apunta a /path/main/.git/worktrees/test-next , luego actualice /path/main/.git/worktrees/test-next/gitdir para referenciar /newpath/test-next lugar.

Tenga cuidado al eliminar una rama: antes de git 2.9 (junio de 2016), podría eliminar una en uso en otro árbol de trabajo.

Cuando la función " git worktree " está en uso, " git branch -d " permitió la eliminación de una sucursal que se haya prestado en otro worktree.

Ver commit f292244 (29 de marzo de 2016) por Kazuki Yamaguchi ( rhenium ) .
Ayudado por: Eric Sunshine ( sunshineco ) .
(Combinado por Junio ​​C Hamano - gitster - in commit 4fca4e3 , 13 de abril de 2016)

branch -d : se niega a eliminar una rama que está actualmente activada

Cuando el árbol de trabajo actual desprotege una rama, se prohíbe eliminarla.
Sin embargo, cuando la rama está desprotegida solo por otros árboles en funcionamiento, la eliminación se realiza incorrectamente.
Use find_shared_symref() para verificar si la rama está en uso, no solo comparando con la CABEZA del árbol de trabajo actual.

De manera similar, antes de git 2.9 (junio de 2016), cambiar el nombre de una sucursal registrada en otro árbol de trabajo no ajustó el HEAD simbólico en dicho árbol de trabajo.

Consulte commit 18eb3a9 (08 de abril de 2016), y commit 70999e9 , commit 2233066 (27 de marzo de 2016) por Kazuki Yamaguchi ( rhenium ) .
(Fusionada por Junio ​​C Hamano - gitster - in commit 741a694 , 18 de abril de 2016)

branch -m : actualizar todas las CABEZAS por trabajo

Al cambiar el nombre de una sucursal, actualmente solo se actualiza el HEAD del árbol de trabajo actual, pero debe actualizar los HEAD de todos los árboles en funcionamiento que apuntan a la rama antigua.

Este es el comportamiento actual, / path / to / wt''s HEAD no se actualiza:

% git worktree list /path/to 2c3c5f2 [master] /path/to/wt 2c3c5f2 [oldname] % git branch -m master master2 % git worktree list /path/to 2c3c5f2 [master2] /path/to/wt 2c3c5f2 [oldname] % git branch -m oldname newname % git worktree list /path/to 2c3c5f2 [master2] /path/to/wt 0000000 [oldname]

Este parche soluciona este problema al actualizar todos los HEAD relevantes del árbol de trabajo al cambiar el nombre de una sucursal.

El mecanismo de bloqueo es oficialmente compatible con git 2.10 (Q3 2016)

Ver commit 080739b , commit 6d30862 , commit 58142c0 , commit 346ef53 , commit 346ef53 , commit 58142c0 , commit 346ef53 , commit 346ef53 (13 Jun 2016), y commit 984ad9e , commit 6835314 (03 Jun 2016) por Nguyễn Thái Ngọc Duy ( pclouds )
Sugerido por: Eric Sunshine ( sunshineco ) .
(Fusionada por Junio ​​C Hamano - gitster - in commit 2c608e0 , 28 jul 2016)

git worktree lock [--reason <string>] <worktree> git worktree unlock <worktree>

Si un árbol de trabajo vinculado se almacena en un dispositivo portátil o recurso compartido de red que no siempre está montado, puede evitar que sus archivos administrativos se git worktree lock al emitir el comando git worktree lock , especificando opcionalmente --reason para explicar por qué el árbol de trabajo está bloqueado .

<worktree> : si los últimos componentes de la ruta en el árbol de trabajo son únicos entre los árboles en funcionamiento, se pueden usar para identificar los árboles de trabajo.
Por ejemplo, si solo tiene que trabajar los árboles en " /abc/def/ghi " y " /abc/def/ggg ", entonces " ghi " o " def/ghi " es suficiente para apuntar al árbol de trabajo anterior.

Git 2.13 (Q2 2017) agrega una opción de lock en commit 507e6e9 (12 de abril de 2017) por Nguyễn Thái Ngọc Duy ( pclouds ) .
Sugerido por: David Taylor ( dt ) .
Ayudado por: Jeff King ( peff ) .
(Fusionada por Junio ​​C Hamano - gitster - in commit e311597 , 26 de abril de 2017)

Permitir bloquear un árbol de trabajo inmediatamente después de su creación.
Esto ayuda a evitar una carrera entre " git worktree add; git worktree lock " y " git worktree prune ".

Así que git worktree add'' --lock es el equivalente a git worktree lock después de git worktree add , pero sin condición de carrera.

Git 2.17+ (Q2 2018) agrega git worktree move / git worktree remove : vea esta respuesta .

Git 2.19 (Q3 2018) agrega una opción " --quiet " para hacer que " git worktree add " sea menos detallado.

Ver commit 371979c (15 de agosto de 2018) de Elia Pinto ( devzero2000 ) .
Ayudado por: Martin Ågren, Duy Nguyen ( pclouds ) y Eric Sunshine ( sunshineco ) .
(Fusionada por Junio ​​C Hamano - gitster - in commit a988ce9 , 27 de agosto de 2018)

worktree : agregar --quiet opción --quiet

Agregue la opción '' --quiet '' a git worktree , como para los otros comandos de git .
'' add '' es el único comando que se ve afectado ya que todos los demás comandos, excepto '' list '', están actualmente en silencio por defecto.


La única solución que se me ocurre es clonar dos directorios y agregarlos como repositorios remotos uno del otro. Luego puede seguir juntando cosas del cambiado hacia el otro sin empujar nada al repositorio remoto.

Supongo que desea tener dos directorios de trabajo y no dos clones del control remoto porque no desea enviar algunas ramas al control remoto. De lo contrario, dos clones de tu control remoto funcionarán bien, solo necesitas hacer algunos empujones para mantener los tres sincronizados.


La distribución de git viene con un script contribuido llamado git-new-workdir . Lo usarías de la siguiente manera:

git-new-workdir project-dir new-workdir branch

donde project-dir es el nombre del directorio que contiene su repositorio .git . Estos scripts crean otro directorio `.git ''con muchos enlaces simbólicos al original, excepto los archivos que no se pueden compartir (como la rama actual), lo que le permite trabajar en dos ramas diferentes.

Suena un poco frágil, pero es una opción.