Introdução
Quando estamos trabalhando em um projeto, muitas vezes precisamos trocar para uma outra branch para ajudar um colega, corrigir algum bug, ou trabalhar em uma outra funcionalidade (por troca de prioridade ou devido a algum impedimento).
Quando isso acontece, temos algumas opções:
Clonar novamente o projeto em outra pasta: Essa era a opção que eu usava até pouco tempo atrás, mas se você estiver trabalhando com um projeto grande, pode levar um tempo para fazer download do repositório remoto, além de usar mais espaço em disco, pois vai resultar em outra cópia do repositório local para cada branch.
Fazer stash ou commit das alterações e checkout da outra branch: Essa opção é ok, mas é mais trabalhosa e não permite ter mais de uma branch em paralelo;
Adicionar uma nova working tree: Essa é a opção que prefiro porque posso ter um único repositório local compartilhado entre as branches.
Nesse post, vou mostrar como utilizar o working trees para trocar branches de forma mais fácil.
Como um repositório Git funciona
Quando usamos o comando git clone
, o Git cria duas coisas no destino: uma working tree e um repositório local, cópia do repositório remoto (pasta .git
dentro da pasta da working tree).
ℹ️
git clone --bare
clona apenas o repositório no destino, sem a working tree.
Repositório
O repositório Git é um diretório estruturado que armazena os objetos, branches e outros componentes utilizados pelo Git para controlar as versões dos nossos arquivos.
Working tree
Uma working tree é onde os nossos arquivos propriamente ditos ficam armazenados. Quando usamos git checkout
, o Git troca todos os arquivos na working tree para refletir os arquivos da branch.
Exemplo
git clone https://github.com/dgenezini/MeuProjeto.git MeuProjeto
Dentro do repositório ficam vários arquivos e pastas, mas para o escopo desse post, esses são os mais importantes:
- objects = Diretório onde são armazenados os blobs (arquivos), trees (diretórios), e commits;
- refs = Diretório onde são armazenados ponteiros para os commits que são os heads de cada branch no repositório;
- HEAD = Arquivo apontando para a branch ou tag da working tree;
- index = Arquivo usado para controlar as alterações pendentes da working tree.
Por que usar Git Worktree?
Usando o comando git worktree
, podemos criar múltiplas working trees apontando para o mesmo repositório local, assim compartilhando a maioria dos componentes entre as working trees.
Em vez de um diretório .git
, as working trees adicionais tem um arquivo .git
apontando para uma pasta dentro do repositório local.
Dentro da pasta da working tree, temos os componentes do Git que não são compartilhados com outras working trees.
Observe que a maioria do repositório, incluindo a pasta objects
(com os arquivos, diretórios e commits), é compartilhada.
Esses são os principais componentes em uma pasta de working tree:
- HEAD = Arquivo apontando para a branch da working tree;
- index = Arquivo usado para controlar as alterações pendentes da working tree;
- commondir = Arquivo apontando para o repositório local.
Usando Git Worktree
Eu gosto de ter todas as working trees como sub-pastas, então eu começo criando uma pasta com o nome do meu repositório e clonando a branch principal para uma pasta com o nome dela (no meu caso, main
).
mkdir MeuProjeto && cd MeuProjeto
git clone https://github.com/dgenezini/MeuProjeto.git main
Esse é a estrutura que teremos:
MeuProjeto/ <-- Nome do repositório
└── main <-- Nome da branch
├── .git <-- Repositório local
└── README.md
ℹ️ Algumas pessoas usam
git clone --bare
para criar o repositório local sem uma working tree, mas a opção--bare
não mapeia as branches locais para suas origens remotas, então eu prefiro clonar uma branch padrão (nesse exemplo, a branchmain
), porque dessa forma eu não preciso mapear manualmente a origem das branches para cada working tree criada.
Criando uma working tree
Dentro do diretório main
, use o comando git worktree add
:
git worktree add [path] [branch]
Exemplo:
cd main
git worktree add ../featureA featureA
Esse é o resultado:
MeuProjeto/ <-- Nome do repositório
├── featureA <-- Nome da branch
│ ├── .git <-- Arquivo apontando para ../main/.git
│ └── README.md
└── main <-- Nome da branch
├── .git <-- Repositório local
└── README.md
ℹ️ Você pode usar o comando
git worktree add
e outros comando do Git dentro de qualquer diretório de working tree.
⚠️ Se estiver usando windows, troque a barra no caminho de
../featureA
para..\featureA
.
Trocando para uma working tree
Apenas mude o diretório onde está trabalhando:
cd ../featureA
Removendo uma working tree
Dentro do diretório main
, use o comando git worktree remove
:
git worktree remove [branch]
Exemplo:
git worktree remove featureA
ou exclua a pasta da working tree (nesse exemplo, featureA
), e use o comando git worktree prune
para remover as working trees que não existem mais.
Extensão Git Worktrees para Visual Studio Code
Git Worktrees é uma extensão gratuita para Visual Studio Code que nos ajuda a trabalhar com working trees.
Criando uma working tree
Abra a paleta de comandos (Ctrl+Shift+P
), procure por worktree add
Trocando para uma working tree
Abra a paleta de comandos (Ctrl+Shift+P
), procure por worktree list
e selecione Git Worktree: List
.
Selecione a branch onde quer trabalhar e o VS Code abrirá uma nova janela com a working tree selecionada.
Removendo uma working tree
Abra a paleta de comandos (Ctrl+Shift+P
), procure por worktree remove
e selecione Git Worktree: Remove
.
Selecione a branch que quer remover.
⚠️ Você não pode remover a working tree que está aberta no VS Code.
Trocando para uma working tree pelo Visual Studio 2022
O Visual Studio é a minha IDE favorita para trabalhar com .NET, então é importante que eu consiga trocar de forma fácil entre working trees através dele.
Uma vez que a working tree foi aberta pela primeira vez no Visual Studio, ele irá rastrear ela como um repositório na barra de status. Para trocar de working tree, basta trocar o repositório: