Não tenho certeza se isso é algo suportado pelo Git, mas em teoria parece que deve funcionar para mim.
Meu fluxo de trabalho geralmente envolve minha edição de arquivos em várias ramificações simultaneamente. Em outras palavras, geralmente desejo abrir alguns arquivos em uma ramificação enquanto edito o conteúdo de outro arquivo em outra ramificação.
Minha solução típica para isso é fazer dois checkouts, mas é uma pena não poder compartilhar ramos e referências entre eles. O que eu gostaria é ter apenas dois diretórios de trabalho gerenciados pela mesma pasta .git.
Estou ciente das soluções locais de clones git (o padrão, que é o de vincular objetos compartilhados, e a opção --shared, que configura um armazenamento de objetos alternativo com o repositório original), mas essas soluções reduzem o uso de espaço em disco , e especialmente no caso de --shared, parecem repletos de perigos.
Existe uma maneira de usar uma pasta .git e ter dois diretórios de trabalho apoiados por ela? Ou o Git está codificado para ter apenas um diretório ativo em check-out a qualquer momento?
git-new-workdir
será substituído porgit checkout --to=<path>
no Git 2.5. Veja minha resposta abaixogit worktree add <path> [<branch>]
(Git 2.5 rc2). Veja minha resposta editada abaixoRespostas:
O Git 2.5 propõe desde julho de 2015 um substituto para
contrib/workdir/git-new-workdir
: git worktreeVeja commit 68a2e6a por Junio C Hamano (
gitster
) .A nota de versão menciona :
Consulte commit 799767cc9 (Git 2.5rc2)
Isso significa que agora você pode fazer uma
git worktree add <path> [<branch>]
Aviso: ainda existe uma seção
git worktree
"BUGS" para estar ciente.Nota: com o git 2.7rc1 (novembro de 2015), você pode listar suas ruas de trabalho.
Veja cometer bb9c03b , cometer 92718b7 , cometer 5.193.490 , cometer 1ceb7f9 , cometer 1ceb7f9 , cometer 5.193.490 , cometer 1ceb7f9 , cometer 1ceb7f9 (08 de outubro de 2015), cometer 92718b7 , cometer 5.193.490 , cometer 1ceb7f9 , cometer 1ceb7f9 (08 de outubro de 2015), cometer 5.193.490 , confirmar 1ceb7f9 (08 de outubro de 2015), confirmar 1ceb7f9 (08 de outubro de 2015) e confirmar ac6c561(02 de outubro de 2015) por Michael Rappazzo (
rappazzo
) .(Mesclado por Junio C Hamano -
gitster
- in commit a46dcfb , 26 de outubro de 2015)Por exemplo:
Nota: se você mover uma pasta da árvore de trabalho, precisará atualizar manualmente o
gitdir
arquivo.Consulte commit 618244e (22 de janeiro de 2016) e commit d4cddd6 (18 de janeiro de 2016) por Nguyễn Thái Ngọc Duy (
pclouds
) .Ajudado por: Eric Sunshine (
sunshineco
) .(Mesclado por Junio C Hamano -
gitster
- na confirmação d0a1cbc , 10 de fevereiro de 2016)O novo documento no git 2.8 (março de 2016) incluirá:
Cuidado ao excluir uma ramificação: antes do git 2.9 (junho de 2016), era possível excluir uma em uso em outra árvore de trabalho.
Consulte commit f292244 (29 de março de 2016) por Kazuki Yamaguchi (
rhenium
) .Ajudado por: Eric Sunshine (
sunshineco
) .(Incorporado por Junio C Hamano -
gitster
- in commit 4fca4e3 , 13 de abril de 2016)Da mesma forma, antes do git 2.9 (junho de 2016), renomear uma ramificação com check-out em outra árvore de trabalho não ajustava o HEAD simbólico na referida outra árvore de trabalho.
Consulte commit 18eb3a9 (08 de abril de 2016) e commit 70999e9 , commit 2233066 (27 de março de 2016) por Kazuki Yamaguchi (
rhenium
) .(Mesclado por Junio C Hamano -
gitster
- na confirmação 741a694 , 18 de abril de 2016)O mecanismo de bloqueio é oficialmente suportado pelo git 2.10 (terceiro trimestre de 2016)
Consulte commit 080739b , commit 6d30862 , commit 58142c0 , commit 346ef53 , commit 346ef53 , commit 58142c0 , commit 346ef53 , commit 346ef53 (13 de junho de 2016) e commit 984ad9e , commit 684349 (03 jun 2016) por Nguyễn Thái Ngọc Duy (
pclouds
) .Sugerido por: Eric Sunshine (
sunshineco
) .(Mesclado por Junio C Hamano -
gitster
- na confirmação 2c608e0 , 28 de julho de 2016)Git 2.13 (Q2 2017) adiciona uma
lock
opção no commit 507e6e9 (12 de abril de 2017) por Nguyễn Thái Ngọc Duy (pclouds
) .Sugerido por: David Taylor (
dt
) .Ajudado por: Jeff King (
peff
) .(Mesclado por Junio C Hamano -
gitster
- no commit e311597 , 26 de abril de 2017)Assim
git worktree add' --lock
é o equivalente agit worktree lock
depoisgit worktree add
, mas sem condição de corrida.O Git 2.17+ (Q2 2018) adiciona
git worktree move
/git worktree remove
: veja esta resposta .O Git 2.19 (terceiro trimestre de 2018) adiciona uma
--quiet
opção " " para tornar "git worktree add
" menos detalhada.Veja commit 371979c (15 de agosto de 2018) de Elia Pinto (
devzero2000
) .Ajudado por: Martin Ågren, Duy Nguyen (
pclouds
) e Eric Sunshine (sunshineco
) .(Incorporado por Junio C Hamano -
gitster
- in commit a988ce9 , 27 de agosto de 2018)Note que "
git worktree add
" costumava fazer um "encontre um nome disponível com stat e depoismkdir
", que é propenso à corrida.Isso foi corrigido no Git 2.22 (Q2 2019) usando
mkdir
e reagindoEEXIST
em um loop.Veja commit 7af01f2 (20 fev 2019) por Michal Suchanek (
hramrach
) .(Mesclado por Junio C Hamano -
gitster
- in commit 20fe798 , 09 abr 2019)O Git 2.22 (Q2 2019) corrige a lógica para saber se um repositório do Git tem uma árvore de trabalho "
git branch -D
" que protege de remover o ramo que está atualmente com check-out por engano.A implementação dessa lógica foi interrompida para repositórios com nome incomum, que infelizmente é a norma para submódulos atualmente.
Veja commit f3534c9 (19 Apr 2019) por Jonathan Tan (
jhowtan
) .(Mesclado por Junio C Hamano -
gitster
- in commit ec2642a , 08 de maio de 2019)fonte
A
git
distribuição vem com um script contribuído chamadogit-new-workdir
. Você usaria da seguinte maneira:onde project-dir é o nome do diretório que contém seu
.git
repositório. Esse script cria outro.git
diretório com muitos links simbólicos para o original, exceto arquivos que não podem ser compartilhados (como o ramo atual), permitindo que você trabalhe em dois ramos diferentes.Parece um pouco frágil, mas é uma opção.
fonte
git-new-workdir-recursive
qual é o invólucrogit-new-workdir
.Me deparei com essa pergunta esperando uma solução que não encontrei aqui. Portanto, agora que eu tinha encontrar o que eu precisava, eu decidi postá-lo aqui para os outros.
Advertência: Essa provavelmente não é uma boa solução se você precisar editar várias ramificações simultaneamente, como estados OP. É por ter várias ramificações verificadas simultaneamente que você não pretende editar. (Vários diretórios de trabalho suportados por uma pasta .git.)
Aprendi algumas coisas desde que vim a essa pergunta pela primeira vez:
O que é um " repositório vazio ". É essencialmente o conteúdo do
.git
diretório, sem estar localizado em uma árvore de trabalho.O fato de você poder especificar o local do repositório que está usando (o local do seu
.git
diretório) na linha de comando com agit
opção--git-dir=
O fato de você poder especificar o local da sua cópia de trabalho com
--work-tree=
O que é um "repositório de espelho".
Esta última é uma distinção muito importante. Na verdade, não quero trabalhar no repositório, só preciso que cópias de diferentes ramos e / ou tags sejam verificadas simultaneamente. Na verdade, preciso garantir que as ramificações não sejam diferentes das ramificações do meu controle remoto. Então, um espelho é perfeito para mim.
Portanto, no meu caso de uso, consegui o que precisava fazendo:
A grande ressalva sobre isso é que não há um HEAD separado para as duas cópias. Portanto, após o exposto, a execução
git --git-dir=<localgitdir> --work-tree=firstcopy status
mostrará todas as diferenças de branch2 para branch1 como alterações não confirmadas - porque HEAD está apontando para branch2. (É por isso que uso a-f
opçãocheckout
, porque, na verdade, não pretendo fazer alterações localmente. Posso fazer check-out de qualquer tag ou ramificação para qualquer árvore de trabalho, desde que use a-f
opção.)Para o meu caso de uso, com vários checkouts coexistindo no mesmo computador sem precisar editá-los , isso funciona perfeitamente. Não sei se existe alguma maneira de ter vários HEADs para as várias árvores de trabalho sem um script como o descrito nas outras respostas, mas espero que isso seja útil para outra pessoa.
fonte
$HOME
. Há uma outra ressalva sobre o método acima que descobri mais tarde, que tem a ver com arquivos que não existem em um ou outro ramo. Se você fizer check-out de A em dir1, check-out de B em dir2 e forçar check-out C em dir1, se houver um arquivo que exista em A, mas não em B ou C, o arquivo não será removido do dir1, nem mesmo pelo force checkout . Portanto, você pode precisar experimentargit clean
nesse caso - ou fazer o que eu fiz, e simplesmente usar esse método para preencher um diretório recém-criado.A única solução em que consigo pensar é clonar dois diretórios e adicioná-los como repositórios remotos um do outro. Em seguida, você pode continuar puxando coisas de uma para outra sem realmente enviar nada para o repositório remoto.
Suponho que você queira ter dois diretórios de trabalho e não dois clones do controle remoto, porque não deseja enviar algumas ramificações para o controle remoto. Caso contrário, dois clones do seu controle remoto funcionariam bem - você só precisa pressionar e puxar para manter os três sincronizados.
fonte