Como lidar com 'error: untracked working tree files would be overwritten by checkout' no Git

GitBeginner
Pratique Agora

Introdução

Git é um poderoso sistema de controle de versão essencial para o desenvolvimento de software moderno. Ao usar Git, você pode encontrar a mensagem de erro: "error: untracked working tree files would be overwritten by checkout". Este erro ocorre quando você tenta mudar de branch, mas o Git detecta que essa ação sobrescreveria arquivos no seu diretório de trabalho atual que ainda não são rastreados pelo Git. Este recurso de segurança evita a perda acidental de dados.

Neste laboratório, você aprenderá a causa deste erro comum, como identificar os arquivos conflitantes e vários métodos para resolvê-lo. Ao final deste tutorial, você será capaz de gerenciar seu fluxo de trabalho Git de forma mais eficaz e lidar com este erro com confiança.

Este é um Lab Guiado, que fornece instruções passo a passo para ajudá-lo a aprender e praticar. Siga as instruções cuidadosamente para completar cada etapa e ganhar experiência prática. Dados históricos mostram que este é um laboratório de nível iniciante com uma taxa de conclusão de 88%. Recebeu uma taxa de avaliações positivas de 90% dos estudantes.

Replicando o Erro de Checkout

Para entender como corrigir o erro, primeiro precisamos replicá-lo. Isso ajudará a esclarecer por que o Git relata um conflito. Nosso script de configuração já criou um repositório Git com dois branches: main e feature-branch. O feature-branch contém um arquivo que agora criaremos localmente no branch main.

Primeiro, navegue até o diretório do projeto. Todos os comandos neste laboratório serão executados a partir deste diretório.

cd ~/project/git-checkout-demo

Vamos verificar o status atual do nosso repositório para garantir que tudo esteja limpo.

git status

A saída deve ser:

On branch main
nothing to commit, working tree clean

Isso confirma que estamos no branch main sem alterações pendentes. Agora, vamos listar os branches disponíveis.

git branch

Você verá os dois branches, com * indicando o branch atual:

  feature-branch
* main

Agora, vamos criar o conflito. Criaremos um novo arquivo chamado feature.md em nosso diretório de trabalho atual. Este arquivo está atualmente "não rastreado" (untracked) pelo Git no branch main, mas um arquivo com o mesmo nome já existe e é rastreado no feature-branch.

echo "## My local changes to feature documentation" > feature.md

Verifique o status novamente para ver o novo arquivo não rastreado.

git status

A saída agora mostra feature.md como um arquivo não rastreado:

On branch main
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	feature.md

nothing added to commit but untracked files present (use "git add" to track)

Finalmente, vamos tentar mudar para o feature-branch.

git checkout feature-branch

Este comando falhará e produzirá o erro que estamos estudando:

error: The following untracked working tree files would be overwritten by checkout:
	feature.md
Please move or remove them before you switch branches.
Aborting

O Git abortou o checkout para proteger seu arquivo local não rastreado feature.md de ser sobrescrito pela versão do feature-branch. Nas próximas etapas, exploraremos diferentes maneiras de resolver isso.

Resolvendo o Conflito com git stash

Uma das maneiras mais seguras e comuns de resolver este erro é usando git stash. Este comando salva temporariamente suas modificações locais (tanto as preparadas quanto as não preparadas) e reverte o diretório de trabalho para corresponder ao último commit. Isso permite que você mude de branch livremente.

Atualmente estamos no branch main com o arquivo não rastreado feature.md causando o conflito.

Para fazer o stash de arquivos não rastreados, você precisa usar a opção --include-untracked (ou -u).

git stash push --include-untracked

Você verá uma mensagem de confirmação:

Saved working directory and index state WIP on main: <commit_hash> Initial commit with README

Agora, verifique o status do seu repositório novamente.

git status

O diretório de trabalho está limpo e o arquivo não rastreado desapareceu:

On branch main
nothing to commit, working tree clean

Com o diretório de trabalho limpo, você agora pode mudar para o feature-branch sem nenhum erro.

git checkout feature-branch

O comando será bem-sucedido:

Switched to branch 'feature-branch'

Você está agora no feature-branch. Se você inspecionar feature.md, verá a versão que pertence a este branch.

cat feature.md
## Official Feature Documentation

Suas alterações locais estão armazenadas com segurança no stash. Para recuperá-las, você pode voltar para o branch main e aplicar o stash.

git checkout main
git stash pop

O comando git stash pop reaplica as alterações do stash e as remove da lista de stash. Seu arquivo feature.md está agora de volta ao seu diretório de trabalho.

Para o próximo passo, vamos garantir que estamos de volta ao estado de conflito. Se você seguiu o comando git stash pop, você já está lá.

Resolvendo o Conflito com git clean

Outra maneira de resolver o conflito é excluir os arquivos não rastreados. Este método é adequado apenas quando você tem certeza de que não precisa dos arquivos não rastreados. O comando git clean é usado para este propósito.

Aviso: Este comando exclui arquivos permanentemente, portanto, use-o com cautela.

Primeiro, vamos garantir que estamos no estado de conflito no branch main com o arquivo não rastreado feature.md.

cd ~/project/git-checkout-demo
git checkout main
## If feature.md doesn't exist, recreate it
if [ ! -f "feature.md" ]; then echo "## My local changes" > feature.md; fi
git status

Antes de excluir qualquer coisa, é uma boa prática realizar um "dry run" (simulação) usando o flag -n. Isso mostrará quais arquivos seriam excluídos sem realmente excluí-los.

git clean -n

A saída listará os arquivos a serem removidos:

Would remove feature.md

Depois de confirmar que deseja excluir esses arquivos, você pode executar o comando novamente com o flag -f (force).

git clean -f

O Git confirmará a remoção:

Removing feature.md

Agora que o arquivo não rastreado foi removido, seu diretório de trabalho está limpo e você pode mudar de branch sem problemas.

git checkout feature-branch

O checkout será bem-sucedido.

Switched to branch 'feature-branch'

Este método é rápido, mas destrutivo. O método git stash da etapa anterior é geralmente mais seguro porque preserva seu trabalho.

Resolvendo por Rastreamento do Arquivo e Melhores Práticas

Às vezes, o arquivo não rastreado não é descartável; é trabalho que você deseja manter. Neste caso, a abordagem correta é adicionar o arquivo ao sistema de rastreamento do Git, fazendo um commit dele. Esta seção também aborda as melhores práticas para evitar que este erro ocorra em primeiro lugar.

Primeiro, vamos retornar ao branch main e recriar nosso arquivo conflitante.

cd ~/project/git-checkout-demo
git checkout main
echo "## My local changes to feature documentation" > feature.md

Método: Rastrear o Arquivo

Se o arquivo não rastreado for importante, você deve fazer um commit dele no branch atual.

  1. Adicione o arquivo à área de staging.

    git add feature.md
  2. Faça o commit do arquivo preparado.

    git commit -m "Add local version of feature.md"

Agora que suas alterações foram salvas com segurança no branch main, o Git pode lidar com a troca. Ao fazer o checkout de feature-branch, o Git simplesmente substituirá o arquivo no espaço de trabalho pela versão desse branch.

git checkout feature-branch

O checkout é bem-sucedido. Suas alterações commitadas estão seguras no histórico do branch main.

Melhor Prática: Use .gitignore

Para evitar que certos arquivos (como logs, artefatos de build ou arquivos de ambiente) sejam rastreados, você deve usar um arquivo .gitignore. O Git ignorará quaisquer arquivos ou diretórios que correspondam aos padrões em .gitignore, impedindo que se tornem arquivos não rastreados conflitantes.

Vamos criar um arquivo .gitignore para ignorar todos os arquivos .log.

## Switch back to main to add the .gitignore file
git checkout main

## Create the .gitignore file
echo "*.log" > .gitignore

Agora, crie um arquivo de log.

touch app.log

Verifique o status.

git status

Observe que app.log não aparece como um arquivo não rastreado. No entanto, o próprio arquivo .gitignore não está rastreado.

On branch main
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.gitignore

nothing added to commit but untracked files present (use "git add" to track)

Você deve sempre fazer o commit do seu arquivo .gitignore para que as regras sejam compartilhadas em todo o projeto.

git add .gitignore
git commit -m "Add .gitignore to ignore log files"

Ao fazer commits frequentes e usar o .gitignore de forma eficaz, você pode reduzir significativamente as chances de encontrar este erro de checkout.

Resumo

Neste laboratório, você aprendeu a diagnosticar e resolver o "error: untracked working tree files would be overwritten by checkout" no Git.

Você realizou o seguinte:

  1. Replicou o Erro: Você criou com sucesso um cenário que dispara o erro, proporcionando uma compreensão clara de sua causa.
  2. Resolveu com git stash: Você aprendeu a usar git stash para salvar temporariamente arquivos não rastreados, permitindo que você mude de branch com segurança sem perder trabalho.
  3. Resolveu com git clean: Você aprendeu a usar git clean para remover arquivos não rastreados quando eles não são mais necessários, após realizar uma simulação (dry run) para evitar erros.
  4. Resolveu Rastreando Arquivos: Você aprendeu a resolver o problema fazendo um commit do arquivo não rastreado, que é a abordagem correta para trabalho que você pretende manter.
  5. Aprendeu Melhores Práticas: Você aprendeu a usar um arquivo .gitignore para evitar que arquivos temporários ou relacionados a build causem conflitos.

Ao dominar essas técnicas, você pode manter um fluxo de trabalho Git mais limpo e eficiente e lidar com confiança com um dos problemas mais comuns enfrentados pelos desenvolvedores.