Desfazendo Alterações no Git: Reset, Restore e Revert Explicados
O Git é um poderoso sistema de controle de versão que permite rastrear alterações em sua base de código. No entanto, erros acontecem e você pode precisar desfazer alterações. O Git oferece vários comandos para ajudar com isso, mas eles funcionam de maneiras muito diferentes e afetam seu repositório de formas distintas. Compreender as nuances entre git reset, git restore e git revert é crucial para gerenciar efetivamente o histórico do seu projeto e corrigir erros sem consequências indesejadas.
Este artigo desmistificará esses três comandos, explicando seu propósito, como funcionam e quando usar cada um. Utilizaremos a documentação oficial do Git e padrões de uso comuns para fornecer explicações claras e exemplos práticos. Ao final deste guia, você estará equipado para desfazer alterações com confiança, gerenciar seus arquivos preparados e manter um histórico de commits limpo e coerente.
Compreendendo os Conceitos Fundamentais
Antes de mergulhar nos comandos, é importante entender alguns conceitos do Git:
- Diretório de Trabalho (Working Directory): Os arquivos que você está editando atualmente.
- Área de Preparação (Staging Area/Index): Uma área de espera onde você prepara as alterações antes de confirmá-las.
git addmove as alterações do diretório de trabalho para a área de preparação. - Histórico de Commits (Commit History): Uma sequência de instantâneos do seu projeto ao longo do tempo, representados por commits.
- HEAD: Um ponteiro para o commit mais recente no seu branch atual.
Esses três comandos interagem principalmente com essas áreas para modificar ou descartar alterações.
git restore: Para Descartar Alterações no Diretório de Trabalho e na Área de Preparação
O comando git restore, introduzido mais recentemente no Git, foi projetado para a tarefa simples de desfazer alterações no seu diretório de trabalho ou desativar o preparo de arquivos. Geralmente, é considerado mais seguro e intuitivo para essas operações específicas do que o git reset.
Desativando o Preparo de Arquivos
Se você preparou acidentalmente um arquivo usando git add e deseja desativar o preparo, git restore é o comando a ser usado. Ele move as alterações de volta da área de preparação para o seu diretório de trabalho, mas não descarta as modificações em si.
-
Desativar o preparo de um arquivo específico:
bash git restore <file>
Este comando pega a versão do arquivo do índice (área de preparação) e a coloca de volta no índice. Essencialmente, ele remove o arquivo do preparo para o próximo commit, mas as alterações permanecem no seu diretório de trabalho. -
Desativar o preparo de todos os arquivos:
Embora não exista umgit restore .direto para desativar o preparo de tudo da maneira que ogit resetpode fazer, você normalmente aplicariagit restorea arquivos individuais ou o usaria em conjunto com outros comandos, se necessário. No entanto, o caso de uso mais comum é desativar o preparo de arquivos específicos.
Descartando Alterações no Diretório de Trabalho
git restore também pode ser usado para descartar todas as alterações não preparadas no seu diretório de trabalho para um arquivo específico, revertendo-o para a versão na área de preparação (índice) ou para o último estado confirmado.
-
Descartar alterações não preparadas em um arquivo:
bash git restore <file>
(Nota: Este comando pode ter dois significados dependendo do contexto. Quando usado sem--staged, ele atinge principalmente a árvore de trabalho. Se o arquivo estiver preparado, ele o desativa. Se o arquivo for modificado na árvore de trabalho e não estiver preparado, ele reverterá o arquivo da árvore de trabalho para corresponder ao índice.) -
Descartar alterações preparadas e não preparadas para um arquivo (reverter para HEAD):
Para descartar completamente todas as alterações (preparadas e não preparadas) de um arquivo e revertê-lo para o estado em que estava no commitHEAD:
bash git restore --staged --worktree <file>
Este é um comando poderoso que efetivamente redefine o arquivo para seu último estado confirmado.
Restaurando um Arquivo de um Commit Específico
git restore também pode recuperar a versão de um arquivo específico de um commit passado sem alterar o histórico do seu branch.
git restore <file> --source <commit>
Substitua <commit> pelo hash do commit ou por uma referência simbólica como HEAD~1.
git reset: Reescrevendo o Histórico
git reset é um comando mais potente que pode modificar o histórico do seu commit movendo o ponteiro HEAD do branch atual. Ele também pode afetar a área de preparação e o diretório de trabalho, dependendo do modo usado.
Compreendendo os Modos (--soft, --mixed, --hard)
git reset tem três modos principais:
-
--soft: Move oHEADpara o commit especificado, mas deixa sua área de preparação e diretório de trabalho intocados. As alterações dos commits revertidos aparecem como alterações preparadas.
bash git reset --soft HEAD^ # Move o HEAD um commit para trás, as alterações do commit desfeito são preparadas -
--mixed(padrão): Move oHEADe redefine a área de preparação para corresponder ao commit especificado. As alterações dos commits revertidos estão presentes no seu diretório de trabalho, mas não estão preparadas.
bash git reset HEAD^ # Equivalente a git reset --mixed HEAD^ # Move o HEAD um commit para trás, as alterações do commit desfeito não são preparadas -
--hard: Move oHEADe redefine tanto a área de preparação quanto o diretório de trabalho para corresponder ao commit especificado. Isso descarta todas as alterações dos commits que estão sendo revertidos e quaisquer alterações não confirmadas subsequentes no diretório de trabalho. Use com extrema cautela.
bash git reset --hard HEAD~ # Descarta o último commit E todas as alterações desde então no diretório de trabalho e área de preparação
Casos de Uso para git reset:
- Desativar o preparo de arquivos:
git reset <file>é um atalho paragit restore --staged <file>, removendo um arquivo da área de preparação sem afetar o diretório de trabalho. - Desativar o preparo de tudo:
git reset(sem argumentos ou especificandoHEAD) desativa o preparo de todas as alterações atualmente preparadas, movendo-as de volta para o diretório de trabalho (equivalente agit restore --staged .). - Desfazer o último commit:
git reset HEAD^(ougit reset --soft HEAD^) é comumente usado para emendar o último commit. As alterações do commit anterior agora estão preparadas, prontas para serem reenviadas com modificações ou uma nova mensagem. - Descartar todas as alterações locais:
git reset --hardé usado para descartar completamente todas as modificações locais (preparadas e não preparadas) e reverter o repositório para um commit específico. Esta é uma operação destrutiva.
Revertendo um Commit Antigo
Se você precisar desfazer alterações de um commit que não é o mais recente, git reset pode ser usado. Por exemplo, para reverter para um commit antes de um problemático:
# Exemplo: Desfazer os últimos 2 commits, mantendo as alterações não preparadas
git reset --mixed HEAD~2
Aviso: git reset reescreve o histórico. Se você já enviou os commits que está revertendo, isso pode causar problemas significativos para colaboradores. Geralmente é seguro reverter commits que existem apenas no seu repositório local.
git revert: Criando um Novo Commit para Desfazer Alterações
git revert é a maneira mais segura de desfazer alterações em um histórico compartilhado ou publicado. Em vez de reescrever o histórico, ele cria um novo commit que introduz as alterações inversas de um commit anterior.
Como Funciona
Quando você executa git revert <commit>, o Git analisa o commit especificado, calcula as alterações opostas e as aplica ao seu diretório de trabalho e área de preparação atuais. Em seguida, ele solicita que você crie um novo commit com uma mensagem padrão indicando qual commit está sendo revertido.
-
Reverter um commit específico:
bash git revert <commit-hash>
Isso criará um novo commit que desfaz as alterações introduzidas por<commit-hash>. Se houver conflitos de mesclagem, o Git pausará e exigirá que você os resolva antes de confirmar. -
Revertendo múltiplos commits:
Você pode reverter um intervalo de commits:
bash # Reverte commits de HEAD~3 até (mas não incluindo) HEAD git revert HEAD~3..HEAD
O Git tentará criar um commit de reversão para cada commit especificado. Se surgirem conflitos durante o processo, você precisará resolvê-los para cada reversão.
Vantagens do git revert:
- Preserva o Histórico: Não altera commits existentes, tornando-o seguro para branches públicos ou compartilhados.
- Trilha de Auditoria Clara: O commit de reversão declara explicitamente o que foi desfeito e por quê.
- Lida Bem com Merges: O Git frequentemente pode reverter commits de merge automaticamente, embora intervenção manual possa ser necessária para cenários complexos.
Quando Usar git revert:
- Quando você precisa desfazer alterações em um branch que já foi enviado para um repositório remoto.
- Quando você deseja manter um registro claro e imutável de todas as alterações, incluindo correções.
- Ao desfazer um commit de merge.
Escolhendo o Comando Certo
Aqui está um guia simples para ajudá-lo a decidir:
- Para desativar o preparo de um arquivo: Use
git restore <file>ougit reset <file>. - Para descartar alterações não preparadas no seu diretório de trabalho para um arquivo: Use
git restore <file>. - Para descartar todas as alterações (preparadas e não preparadas) para um arquivo: Use
git restore --staged --worktree <file>. - Para desfazer o último commit e manter as alterações preparadas (para emenda): Use
git reset --soft HEAD^. - Para desfazer o último commit e manter as alterações não preparadas: Use
git reset HEAD^. - Para descartar completamente o último commit e todas as alterações subsequentes (destrutivo): Use
git reset --hard HEAD^. - Para desfazer um commit em um branch compartilhado sem reescrever o histórico: Use
git revert <commit-hash>. - Para descartar todas as alterações locais em todo o repositório (destrutivo): Use
git reset --hard.
Conclusão
Dominar git reset, git restore e git revert é fundamental para um uso eficaz do Git. git restore é sua ferramenta principal para descartar alterações com segurança no diretório de trabalho e na área de preparação. git reset oferece poderosas capacidades de reescrita de histórico, melhor usado em commits locais e não enviados. git revert fornece um método seguro e que preserva o histórico para desfazer alterações, especialmente crucial em ambientes colaborativos. Ao entender seus comportamentos distintos e escolher o comando apropriado, você pode gerenciar com confiança a evolução do seu projeto e corrigir quaisquer erros ao longo do caminho.