Tutorial

git checkout, switch e restore: quando usar cada um

Atualizado: · Skillaria.Top

O git checkout faz duas coisas diferentes: troca de branch e restaura arquivos. Por isso, desde o Git 2.23, essas tarefas foram divididas entre o git switch (branches) e o git restore (arquivos). Para trocar de branch use git switch nome, para descartar alterações não commitadas em um arquivo use git restore arquivo, e deixe o checkout para scripts antigos e hábitos já consolidados.

Por que o git checkout tem dois papéis

Historicamente, o git checkout faz duas operações fundamentalmente diferentes. Com o nome de uma branch, ele move o HEAD e atualiza a pasta de trabalho. Com o caminho de um arquivo, ele pega a versão do arquivo do índice ou de um commit e sobrescreve suas alterações sem avisar. O mesmo comando ora troca de branch com segurança, ora joga fora de forma irreversível um trabalho não salvo.

Por isso, no Git 2.23 surgiram dois comandos separados: git switch para branches e git restore para arquivos. O checkout não foi removido e continua funcionando perfeitamente, mas o código novo, a documentação e as próprias dicas do Git usam switch e restore. Se você está aprendendo agora, comece por eles; mesmo assim, é preciso conhecer o checkout — ele aparece em tutoriais, scripts e entrevistas de emprego.

Equivalência entre os comandos

Tarefagit checkoutComando novo
Trocar de branchgit checkout maingit switch main
Criar uma branch e mudar para elagit checkout -b featuregit switch -c feature
Criar ou redefinir uma branchgit checkout -B featuregit switch -C feature
Voltar para a branch anteriorgit checkout -git switch -
Ir para um commit (detached HEAD)git checkout 3f2a1c9git switch --detach 3f2a1c9
Descartar alterações em um arquivogit checkout -- app.jsgit restore app.js
Tirar um arquivo do índicegit reset HEAD app.jsgit restore --staged app.js
Pegar um arquivo de outra branch ou commitgit checkout main -- app.jsgit restore --source=main --staged --worktree app.js
Descartar todas as alterações da pastagit checkout -- .git restore .

Repare no -- nos comandos de checkout. É um separador que significa "daqui em diante vêm caminhos". Ele evita ambiguidade quando um arquivo e uma branch têm o mesmo nome. No restore esse problema não existe, porque o comando trabalha apenas com arquivos.

git checkout para branches

git checkout feature/login        # trocar de branch
git checkout -b feature/login     # criar a partir do commit atual e trocar
git checkout -b hotfix origin/main   # criar a partir de uma branch remota
git checkout -t origin/feature/x  # branch local que rastreia a remota

Se a branch local não existe, mas há uma branch com esse nome no servidor, git checkout feature/x (assim como git switch feature/x) cria a branch local sozinho e configura o rastreamento. Antes disso é preciso um git fetch, senão o Git não sabe da nova branch remota.

A troca de branch não perde alterações não commitadas: elas são levadas para a outra branch, desde que não entrem em conflito com ela. Se houver conflito, o Git recusa e sugere fazer commit ou guardar as alterações com git stash. A flag -f (--force) troca de branch descartando as alterações locais — essa já é uma operação perigosa.

git switch: só branches

O switch repete a parte do checkout ligada a branches, mas com regras mais rígidas. A principal diferença: ele não vai para um commit ou tag sem um --detach explícito. O comando git switch v1.0 dá erro em vez de entrar silenciosamente em detached HEAD, então fica mais difícil acabar "fora de uma branch" por acidente.

git switch main
git switch -c feature/cart
git switch -c feature/cart origin/main
git switch --detach v1.0
git switch -              # branch anterior
git switch -m main        # levar as alterações com merge de três vias

git restore: o botão de desfazer para arquivos

O restore devolve os arquivos a um estado salvo e não mexe no histórico de commits. Para usá-lo com confiança, lembre-se das três áreas do Git: a pasta de trabalho (o que você vê no editor), o índice (o que foi preparado com git add) e os commits.

Como desfazer alterações em um arquivo antes do git add

git restore app.js         # voltar à versão do índice
git restore src/           # todos os arquivos da pasta
git restore .              # todos os arquivos alterados do projeto

Sem flags, o restore restaura a pasta de trabalho a partir do índice. Se o arquivo não foi adicionado ao índice depois do último commit, isso equivale à versão do último commit. As alterações somem sem deixar rastro, não vão para a lixeira, então dê uma olhada no git diff antes de rodar git restore ..

Como tirar um arquivo do índice depois do git add

git restore --staged app.js

O arquivo deixa de estar preparado para o commit, mas suas alterações nele continuam. Esta é a forma mais segura do restore: nada se perde. É exatamente este comando que o git status sugere na seção "Changes to be committed".

Como desfazer tudo: no índice e no arquivo

git restore --staged --worktree app.js
# forma curta
git restore -SW app.js

Como recuperar um arquivo de outro commit ou branch

git restore --source=HEAD~2 app.js          # versão de dois commits atrás
git restore --source=main config.yml        # versão da branch main
git restore --source=3f2a1c9 -- docs/       # uma pasta inteira de um commit

Por padrão, com --source só a pasta de trabalho é alterada. Adicione --staged se quiser já preparar a alteração para o commit. A forma antiga git checkout main -- app.js sempre altera tanto o índice quanto a pasta de trabalho.

Como recuperar um arquivo apagado

git restore deleted.txt                          # apagado, mas ainda não commitado
git restore --source=HEAD~1 deleted.txt          # a exclusão já foi commitada

Se você não sabe em qual commit o arquivo foi apagado, encontre-o com git log --oneline -- deleted.txt. O commit mais recente da lista é aquele em que o arquivo foi removido; a restauração deve ser feita a partir do pai dele: git restore --source=<hash>~1 deleted.txt.

restore, reset e revert: não confunda

Os três comandos "desfazem", mas em profundidades diferentes:

  • restore — trabalha com arquivos na pasta de trabalho e no índice, sem alterar o histórico. Seguro para o time.
  • reset — move o ponteiro da branch para trás, reescrevendo o histórico. --soft mantém as alterações no índice, --mixed (padrão) na pasta de trabalho, --hard as apaga. Perigoso para commits já enviados em branches compartilhadas.
  • revert — cria um novo commit que inverte o commit indicado. O histórico não é reescrito, por isso é o jeito certo de desfazer um commit que já está no servidor.

Regra simples: alterações ainda não commitadas — restore; commit só local — reset; commit que os colegas já têm — revert.

Detached HEAD depois do checkout

Ao executar git checkout 3f2a1c9 ou git checkout v1.0, você verá um longo aviso "You are in 'detached HEAD' state". Agora o HEAD aponta para um commit, e não para uma branch. Isso é prático para olhar uma versão antiga ou rodar os testes nela.

Dá para fazer commits nesse estado, mas os novos commits não vão para nenhuma branch. Se você alterou algo e quer guardar:

git switch -c fix-for-v1

Se estava só olhando, volte: git switch - ou git switch main. Se saiu sem criar a branch, os commits ainda estão acessíveis pelo git reflog: encontre o hash e execute git branch rescue <hash>.

Erros comuns

error: pathspec 'feature' did not match any file(s) known to git

O Git não encontrou nem branch nem arquivo com esse nome. Normalmente a branch existe só no servidor e o fetch não foi feito. Rode git fetch e tente de novo. Confira também a grafia: nomes de branches diferenciam maiúsculas de minúsculas.

Descartei alterações sem querer com checkout -- ou restore

Alterações não commitadas que não estavam no índice não ficam guardadas no Git, e não há como recuperá-las com ferramentas do Git. Resta o histórico local do editor ou da IDE. Já se o arquivo tinha sido adicionado com git add, o conteúdo dele está no banco de objetos como objeto "solto" e pode ser encontrado com git fsck --lost-found.

Arquivo e branch com o mesmo nome

git checkout test, quando existem uma branch test e uma pasta test, mostra um aviso de ambiguidade. Use git switch test para a branch e git restore test (ou git checkout -- test) para os arquivos.

Cenários do dia a dia

Algumas situações que aparecem o tempo todo e o comando certo para cada uma:

  • Começou a editar um arquivo e percebeu que tomou o caminho errado — git restore arquivo.
  • Adicionou ao índice um arquivo a mais antes do commit — git restore --staged arquivo.
  • Precisa mudar de tarefa às pressas no meio do trabalho — git stash, depois git switch branch; ao voltar, git switch - e git stash pop.
  • Quer pegar um único arquivo de uma branch vizinha sem fazer merge da branch inteira — git restore --source=feature/x --staged --worktree caminho.
  • Precisa verificar se o bug existia numa versão anterior — git switch --detach v1.0, teste e depois git switch -.
  • Quer desfazer só parte das alterações de um arquivo — git restore -p arquivo: o Git mostra cada trecho e pergunta se deve descartá-lo.

O modo interativo -p (--patch) é especialmente útil: ele existe tanto no checkout quanto no restore e permite jogar fora a saída de depuração mantendo as alterações úteis no mesmo arquivo.

Como conferir o resultado antes de desfazer

O restore e o checkout com caminhos descartam alterações sem pedir confirmação, então vale a pena ver antes o que exatamente será perdido. git diff mostra as alterações na pasta de trabalho em relação ao índice, git diff --staged o que está preparado para o commit, git diff main -- app.js em que o arquivo difere da versão em outra branch. Na dúvida, guarde o estado atual com git stash: de lá as alterações sempre podem ser recuperadas, ao contrário do restore.

Resumo

O git checkout junta troca de branch e restauração de arquivos, e é justamente isso que o torna perigoso. Para branches use git switch, para arquivos git restore: um comando muda só a posição do HEAD, o outro só o conteúdo dos arquivos. Branches, restore, reset e revert, com bons e maus cenários, são trabalhados na prática no curso de Git.

Perguntas frequentes

O git checkout está obsoleto?

Não, ele não foi declarado obsoleto e continuará funcionando. Só que, no trabalho do dia a dia, recomenda-se usar o git switch e o git restore, que são mais específicos e seguros.

Desde qual versão do Git existem o switch e o restore?

Os dois comandos surgiram no Git 2.23 (2019). Você pode conferir sua versão com git --version.

Dá para desfazer um git restore?

Se foi restaurada a pasta de trabalho, o Git não guardou as alterações descartadas e não há como desfazer. O git restore --staged é seguro: as alterações continuam no arquivo, basta adicioná-las de novo com git add.

Como mudar para a branch de um colega?

Execute git fetch e depois git switch nome-da-branch: o Git cria uma branch local vinculada a origin/nome-da-branch.

Qual a diferença entre git checkout . e git reset --hard?

git checkout . (ou git restore .) devolve os arquivos alterados à versão do índice, sem mexer no índice nem no histórico. git reset --hard redefine o índice e a pasta de trabalho para um commit e, se você passar um commit como argumento, ainda move a branch.

Aprenda este tema em vídeo

Este tema é abordado em profundidade, com prática, no curso “Git do zero ao desenvolvedor confiante”.

Ir para o curso