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 implica la edición de archivos en varias 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 solo dos directorios de trabajo administrados por la misma carpeta .git.
Conozco las soluciones locales de clonación de git (el valor predeterminado, que es para vincular objetos compartidos, y la opción --shared, que configura un almacén de objetos alternativo con el repositorio original), pero estas soluciones solo reducen el uso de espacio en disco , y especialmente en el caso de --compartido, parece estar lleno de peligros.
¿Hay alguna manera de usar una carpeta .git y tener dos directorios de trabajo respaldados por ella? ¿O Git está codificado para tener un solo directorio de trabajo desprotegido en cualquier momento?
git-new-workdir
será reemplazado porgit checkout --to=<path>
en Git 2.5. Vea mi respuesta a continuacióngit worktree add <path> [<branch>]
(Git 2.5 rc2). Vea mi respuesta editada a continuaciónRespuestas:
Git 2.5 propone desde julio de 2015 un reemplazo para
contrib/workdir/git-new-workdir
: git worktreeVer commit 68a2e6a por Junio C Hamano (
gitster
) .La nota de lanzamiento menciona :
Ver commit 799767cc9 (Git 2.5rc2)
Eso significa que ahora puedes hacer un
git worktree add <path> [<branch>]
Advertencia: todavía hay una sección de
git worktree
"ERRORES" para tener en cuenta.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)Por ejemplo:
Nota: si MOVES una carpeta de árbol de trabajo, debes actualizar el archivo manualmente
gitdir
.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á:
Tenga cuidado al eliminar una rama: antes de git 2.9 (junio de 2016), puede eliminar una en uso 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)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)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 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)Entonces
git worktree add' --lock
es el equivalente degit worktree lock
despuésgit 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)Tenga en cuenta que "
git worktree add
" solía hacer un "buscar un nombre disponible con stat y luegomkdir
", que es propenso a la carrera.Esto se ha solucionado con Git 2.22 (Q2 2019) mediante el uso
mkdir
y la reacciónEEXIST
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)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)fuente
La
git
distribución viene con un script contribuido llamadogit-new-workdir
. Lo usarías de la siguiente manera:donde project-dir es el nombre del directorio que contiene su
.git
repositorio. Este script crea otro.git
directorio 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.
fuente
git-new-workdir-recursive
cuál es un contenedor paragit-new-workdir
.Encontré esta pregunta esperando una solución que no encontré aquí. Así que ahora que me he encontrado lo que buscaba, me decidí a publicar aquí para otros.
Advertencia: Probablemente esta no sea una buena solución si necesita editar varias ramas simultáneamente, como los estados de OP. Es por tener varias ramas desprotegidas simultáneamente que no tiene la intención de editar. (Varios directorios de trabajo respaldados por una carpeta .git).
Aprendí algunas cosas desde que llegué a esta pregunta la primera vez:
Qué es un " repositorio desnudo ". Es esencialmente el contenido del
.git
directorio, sin estar ubicado en un árbol de trabajo.El hecho de que puede especificar la ubicación del repositorio que está utilizando (la ubicación de su
.git
directorio) en la línea de comando con lagit
opción--git-dir=
El hecho de que puede especificar la ubicación de su copia de trabajo con
--work-tree=
Qué es un "repositorio de espejos".
Esta última es una distinción bastante importante. En realidad no quiero trabajar en el repositorio, solo necesito tener copias de diferentes ramas y / o etiquetas revisadas simultáneamente. De hecho, necesito garantizar que las ramas no sean diferentes de las ramas de mi control remoto. Entonces un espejo es perfecto para mí.
Entonces, para mi caso de uso, obtuve lo que necesitaba haciendo:
La gran advertencia sobre esto es que no hay un HEAD separado para las dos copias. Entonces, después de lo anterior, la ejecución
git --git-dir=<localgitdir> --work-tree=firstcopy status
mostrará todas las diferencias de branch2 a branch1 como cambios no confirmados, porque HEAD apunta a branch2. (Es por eso que uso la-f
opcióncheckout
, porque en realidad no estoy planeando hacer ningún cambio localmente. Puedo verificar cualquier etiqueta o rama para cualquier árbol de trabajo, siempre que use la-f
opción).Para mi caso de uso de múltiples pagos coexistentes en la misma computadora sin necesidad de editarlos , esto funciona perfectamente. No sé si hay alguna manera de tener múltiples HEADs para los múltiples árboles de trabajo sin un script como se cubre en las otras respuestas, pero espero que esto sea útil para alguien más de todos modos.
fuente
$HOME
. Hay otra advertencia sobre el método anterior que descubrí más adelante, que tiene que ver con archivos que no existen en una u otra rama. Si desprotege A en dir1, luego desprotege B en dir2, luego fuerza forzar desprotección C en dir1, si hay un archivo que existe en A pero no en B o C, el archivo no se eliminará de dir1 ni siquiera mediante la desviación forzada . Por lo tanto, es posible que necesite experimentargit clean
en tal caso, o hacer lo que hice, y simplemente usar este método para llenar un directorio recién creado.La única solución que se me ocurre es clonar dos directorios y agregarlos como repositorios remotos entre sí. A continuación, puede seguir arrastrando cosas del uno modificado al otro sin enviar nada al repositorio remoto.
Supongo que desea tener dos directorios que funcionen y no dos clones del control remoto porque no desea insertar algunas ramas en el control remoto. De lo contrario, dos clones de su control remoto funcionarían bien, solo necesita hacer algunos empujones y tirones para mantener los tres sincronizados.
fuente