Git 2.5 propone desde julio de 2015 un reemplazo para contrib/workdir/git-new-workdir
: git worktree
Ver commit 68a2e6a por Junio C Hamano ( gitster
) .
La nota de lanzamiento menciona :
Un reemplazo para contrib/workdir/git-new-workdir
eso no se basa en enlaces simbólicos y hace que el intercambio de 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 puedes hacer ungit worktree add <path> [<branch>]
Crear <path>
y pagar <branch>
en él. El nuevo directorio de trabajo está vinculado al repositorio actual, compartiendo todo excepto archivos específicos del directorio de trabajo como HEAD, index, etc. La git worktree
sección agrega:
Un repositorio git puede soportar múltiples árboles de trabajo , lo que le permite retirar más de una rama a la vez.
Con git worktree add
un nuevo árbol de trabajo está asociado 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 del repositorio
$GIT_DIR/worktrees
.
El nombre del subdirectorio privado suele ser el nombre base de la ruta del árbol de trabajo vinculado, posiblemente junto 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
/path/other/test-next
y
- también crea un
$GIT_DIR/worktrees/test-next
directorio (o $GIT_DIR/worktrees/test-next1
si test-next
ya está tomado).
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 señalar de nuevo al árbol de trabajo principal $GIT_DIR
(por ejemplo /path/main/.git
).
Esta configuración se realiza en un .git
archivo 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 eventualmente se eliminarán automáticamente (ver gc.pruneworktreesexpire
en git config
), o puede ejecutar git worktree prune
en el árbol de trabajo principal o vinculado para limpiar los archivos administrativos obsoletos.
Advertencia: todavía hay una sección de git worktree
"ERRORES" para tener en cuenta.
El soporte para submódulos está incompleto .
NO se recomienda realizar múltiples pagos de un superproyecto.
Nota: con git 2.7rc1 (noviembre de 2015) puede enumerar sus árboles de trabajo.
Ver cometer bb9c03b , comprometerse 92718b7 , comprometerse 5.193.490 , comprometerse 1ceb7f9 , comprometerse 1ceb7f9 , comprometerse 5.193.490 , comprometerse 1ceb7f9 , cometen 1ceb7f9 (viernes, 08 Oct 2015), comprometerse 92718b7 , comprometerse 5.193.490 , comprometerse 1ceb7f9 , cometen 1ceb7f9 (viernes, 08 Oct 2015), comprometerse 5.193.490 , commit 1ceb7f9 (08 de octubre de 2015), commit 1ceb7f9 (08 de octubre de 2015) y commit ac6c561(02 de octubre de 2015) por Michael Rappazzo ( rappazzo
) .
(Fusionada por Junio C Hamano - gitster
- en commit a46dcfb , 26 oct 2015)
worktree
: Agregar list
comando ' '
' git worktree list
' itera a través de la lista de árbol de trabajo y muestra detalles del árbol de trabajo, incluida la ruta al árbol de trabajo, la revisión y la rama actualmente desprotegidos, 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 una 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 'desnudo' y 'separado') se enumeran 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 MOVES una carpeta de árbol de trabajo, debes actualizar el archivo manualmentegitdir
.
Ver 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
- en commit d0a1cbc , 10 feb 2016)
El nuevo documento en git 2.8 (marzo de 2016) incluirá:
Si mueve un árbol de trabajo vinculado, debe actualizar el gitdir
archivo ' ' en el directorio de la entrada.
Por ejemplo, si se mueve un árbol de trabajo vinculado /newpath/test-next
y su .git
archivo apunta /path/main/.git/worktrees/test-next
, entonces actualice
/path/main/.git/worktrees/test-next/gitdir
a referencia en su /newpath/test-next
lugar.
Tenga cuidado al eliminar una rama: antes de git 2.9 (junio de 2016), puede eliminar una en uso en otro árbol de trabajo.
Cuando la " git worktree
" característica está en uso "," git branch -d
"permitió la eliminación de una rama que está desprotegida en otro árbol de trabajo.
Ver commit f292244 (29 de marzo de 2016) por Kazuki Yamaguchi ( rhenium
) .
Ayudado por: Eric Sunshine ( sunshineco
) .
(Fusionada por Junio C Hamano - gitster
- en commit 4fca4e3 , 13 abr 2016)
branch -d
: rechazar la eliminación de una rama que está actualmente desprotegida
Cuando una rama es desprotegida por el árbol de trabajo actual, está prohibido eliminar la rama.
Sin embargo, cuando la rama se desprotege solo por otros árboles de trabajo, la eliminación se realiza incorrectamente.
Utilícelo find_shared_symref()
para verificar si la rama está en uso, no solo comparándola con el HEAD del árbol de trabajo actual.
De manera similar, antes de git 2.9 (junio de 2016), al cambiar el nombre de una rama desprotegida en otro árbol de trabajo no se ajustó la CABEZA simbólica en dicho otro árbol de trabajo.
Ver 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
- en commit 741a694 , 18 abr 2016)
branch -m
: actualizar todos los HEADs por árbol de trabajo
Al cambiar el nombre de una rama, actualmente solo se actualiza el HEAD del árbol de trabajo actual, pero debe actualizar HEADs de todos los árboles de trabajo que apuntan a la rama anterior.
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 corrige este problema actualizando todos los HEAD de trabajo relevantes al cambiar el nombre de una rama.
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 de junio de 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
- en 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 eliminen emitiendo el git worktree lock
comando, especificando opcionalmente --reason
para explicar por qué el árbol de trabajo está bloqueado.
<worktree>
: Si los últimos componentes de la ruta del árbol de trabajo son únicos entre los árboles de trabajo, se pueden usar para identificar árboles de trabajo.
Por ejemplo, si solo tiene que trabajar árboles en " /abc/def/ghi
" y " /abc/def/ggg
", entonces " ghi
" o " def/ghi
" es suficiente para señalar el árbol de trabajo anterior.
Git 2.13 (Q2 2017) agrega una lock
opción 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
) .
(Fusión por Junio C Hamano - gitster
- en commit e311597 , 26 abr 2017)
Permitir bloquear un árbol de trabajo inmediatamente después de crearlo
Esto ayuda a prevenir una carrera entre " git worktree add; git worktree lock
" y " git worktree prune
".
Entonces git worktree add' --lock
es el equivalente de git worktree lock
después 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 " --quiet
" opción para hacer " git worktree add
" menos detallado.
Ver commit 371979c (15 de agosto de 2018) por Elia Pinto ( devzero2000
) .
Ayudado por: Martin Ågren, Duy Nguyen ( pclouds
) y Eric Sunshine ( sunshineco
) .
(Fusionada por Junio C Hamano - gitster
- en commit a988ce9 , 27 ago 2018)
worktree
: agregar --quiet
opción
Agregue la --quiet
opción ' ' a git worktree
, como para los otros git
comandos.
' add
' es el único comando afectado por él, ya que todos los demás comandos, excepto ' list
', están actualmente en silencio de forma predeterminada.
Tenga en cuenta que " git worktree add
" solía hacer un "buscar un nombre disponible con stat y luego mkdir
", que es propenso a la carrera.
Esto se ha solucionado con Git 2.22 (Q2 2019) mediante el uso mkdir
y la reacción EEXIST
en bucle.
Ver commit 7af01f2 (20 de febrero de 2019) por Michal Suchanek ( hramrach
) .
(Fusionada por Junio C Hamano - gitster
- en commit 20fe798 , 09 abr 2019)
worktree
: worktree add
carrera fija
Git ejecuta un bucle de estadísticas para encontrar un nombre de árbol de trabajo que esté disponible y luego lo hace mkdir
en el nombre encontrado. Conviértalo
en mkdir
bucle para evitar otra invocación de worktree add encontrando el mismo nombre libre y creando primero el directorio.
Git 2.22 (Q2 2019) corrige la lógica para saber si un repositorio de Git tiene un árbol que funciona " git branch -D
" protege de la eliminación de la rama que actualmente está desprotegida por error.
La implementación de esta lógica se rompió para los repositorios con un nombre inusual, que desafortunadamente es la norma para los submódulos en estos días.
Ver commit f3534c9 (19 abr 2019) por Jonathan Tan ( jhowtan
) .
(Fusionada por Junio C Hamano - gitster
- en commit ec2642a , 08 de mayo de 2019)
Solicitudes de extracción de código 178 Insights
worktree
: actualizar is_bare
heurística
Cuando git branch -D <name>
se ejecuta " ", Git generalmente primero verifica si esa rama está actualmente desprotegida.
Pero esta comprobación no se realiza si el directorio Git de ese repositorio no está en " <repo>/.git
", que es el caso si ese repositorio es un submódulo que tiene su directorio Git almacenado como " super/.git/modules/<repo>
", por ejemplo.
Esto hace que la rama se elimine aunque esté desprotegida.
Esto se debe a que get_main_worktree()
en los worktree.c
conjuntos is_bare
de un árbol de trabajo solo se utiliza la heurística de que un repositorio está vacío si la ruta del árbol de trabajo no termina en " /.git
", y no está vacío de lo contrario.
Este is_bare
código se introdujo en 92718b7 (" worktree
: agregar detalles a la estructura del árbol de trabajo", 2015-10-08, Git v2.7.0-rc0), siguiendo una pre-core.bare
heurística.
Este parche hace 2 cosas:
- Enseñe
get_main_worktree()
a usar is_bare_repository()
en su lugar, introducido en 7d1864c ("Introducir is_bare_repository () y core.bare configuration variable", 2007-01-07, Git v1.5.0-rc1) y actualizado en e90fdc3 ("Limpieza del manejo del árbol de trabajo", 2007 -08-01, Git v1.5.3-rc4).
Esto resuelve el " git branch -D <name>
" problema descrito anteriormente.
Sin embargo ... Si un repositorio tiene core.bare=1
pero el git
comando " " se está ejecutando desde uno de sus árboles de trabajo secundarios, is_bare_repository()
devuelve falso (lo cual está bien, ya que hay un árbol de trabajo disponible).
Y, tratar el árbol de trabajo principal como no desnudo cuando está desnudo causa problemas:
Por ejemplo, no eliminar una rama de un árbol de trabajo secundario al que se refiere el HEAD de un árbol de trabajo principal, incluso si ese árbol de trabajo principal está vacío.
Para evitar eso, verifique también core.bare
al configurar is_bare
.
Si core.bare=1
, confía en él, y de lo contrario, úsalo is_bare_repository()
.
git-new-workdir
será reemplazado porgit checkout --to=<path>
en Git 2.5. Vea mi respuesta a continuación