Se você já se aventurou no mundo do desenvolvimento de software, provavelmente já experimentou a necessidade de voltar atrás em algum commit que você fez.
Neste guia, vamos explorar como desfazer commits locais no Git, uma habilidade essencial para qualquer desenvolvedor. Vamos dar uma olhada nos conceitos básicos, aprender a realizar commits e, é claro, descobrir como desfazê-los quando necessário.
Mão na massa
Conceitos Básicos do Git
O que é o Git?
O Git é um sistema de controle de versão amplamente usado na programação. Ele permite que você mantenha o controle das alterações em seu código ao longo do tempo, facilitando portanto o trabalho em equipe e garantindo que você possa voltar a versões anteriores do seu projeto quando necessário.
Por que é importante entender o controle de versão?
Entender o controle de versão é fundamental porque ele ajuda a evitar a perda de trabalho, facilita a colaboração com outros desenvolvedores e permite que você rastreie o histórico de alterações do seu projeto.
Preparação para Desfazer Commits Locais
Configuração do ambiente de desenvolvimento
Certifique-se de que o Git esteja instalado no seu sistema. Você pode verificar isso executando o comando git --version
no seu terminal. Exemplo:
❯ git --version
git version 2.30.1 (Apple Git-130)
Clonagem de um repositório Git localmente
Para começar a trabalhar com um projeto Git, você precisa cloná-lo localmente. Use o comando git clone
seguido do URL do repositório.
Por exemplo, vamos imaginar que você tem um repositório git chamado seu-projeto
:
git clone https://github.com/seu-usuario/seu-projeto.git
Como realizar um commit no Git
Após feito modificações no seu projeto, você chegou ao momento de commitar as mudanças. Esse momento envolve dois passos:
- Adicionar os arquivos desejado ao
stage
- Commitar as mudanças fornecendo uma mensagem de commit.
O que significa o Working Directory e o Stage?
Vamos entender rapidamente o que significa o Stage (ou área de preparação) e o Working Directory (ou diretório de trabalho) em um repositório Git:
Working Directory (Diretório de Trabalho)
O Working Directory é a área onde você trabalha nos seus arquivos e faz todas as alterações no código-fonte do seu projeto. Ela é a pasta local no seu sistema de arquivos que contém todos os arquivos do seu projeto Git.
Os arquivos no Working Directory podem assumir vários estados: não rastreados, modificados ou prontos para confirmação.
Stage (Área de Preparação)
A Stage, também conhecida como área de preparação ou índice, é um espaço intermediário entre o Working Directory e o repositório Git. Quando você faz alterações nos arquivos do Working Directory e deseja incluir essas alterações em um próximo commit, você as adiciona à Stage.
A Stage é onde você seleciona quais alterações específicas deseja incluir no próximo commit. Uma vez que as alterações estão na Stage, você pode confirmá-las como parte de um commit, criando assim um novo snapshot do projeto no repositório Git.
Como adicionar alterações aos arquivos ao stage?
Antes de fazer um commit, você precisa adicionar as alterações desejadas à área de stage. Use o comando git add
para isso.
git add nome-do-arquivo
Comando git commit
e sua sintaxe
O comando git commit
é usado para criar um novo commit com as alterações que estão no stage👈. Certifique-se de adicionar uma mensagem descritiva para o commit:
git commit -m "Mensagem descritiva do commit"
Identificando commits locais
Como listar commits locais
Use o comando git log
para listar todos os commits locais no seu projeto. Isso exibirá o histórico de commits, incluindo o hash do commit, autor, data e mensagem.
git log
Entendendo o git log
O comando git log
é usado para visualizar o histórico de commits em um repositório Git. O formato padrão de saída do git log
apresenta as informações de cada commit em um formato específico que inclui várias seções:
- Hash do Commit: O hash (ou identificador) único de cada commit é exibido na parte superior. Este hash é uma sequência alfanumérica que identifica de forma exclusiva aquele commit específico.
- Autor: O nome do autor do commit é mostrado logo abaixo do hash. Isso indica quem fez o commit.
- Data: A data e hora em que o commit foi feito são exibidas após o nome do autor.
- Mensagem do Commit: A mensagem do commit é uma descrição curta e informativa das alterações realizadas no commit. Ela fornece uma visão geral do que foi feito no commit.
Aqui está um exemplo de saída típica do git log
:
commit 4a3e2d1f4abef7d1c41e64d3f3e7fbb5a3b8e56d
Author: Pedro <pedro@codigo35.com>
Date: Fri Sep 10 15:30:45 2023 -0400
Adiciona funcionalidade de login
commit 8f76b93a2c3e89b2c47f5aaabf4df4e54faccfb9
Author: Pedro <pedro@codigo35.com>
Date: Wed Sep 8 09:15:22 2023 -0400
Corrige bug de exibição no layout
commit 2e1c8378d92e16449ff63cf69b86271b19f54a7d
Author: Pedro <pedro@codigo35.com>
Date: Mon Sep 6 18:47:11 2023 -0400
Inicia projeto do site
Neste exemplo, temos três commits no histórico. Cada commit é representado com o hash, autor, data e a mensagem associada a ele. Isso permite que os desenvolvedores vejam rapidamente o que foi feito em cada commit e rastreiem o histórico do projeto.
Desfazendo commits locais usando o git reset
Explicação do comando git reset
O comando git reset
é usado para desfazer commits locais. Existem três opções principais: --soft
, --mixed
e --hard
. Exploraremos cada uma delas.
Tipos de git reset | Efeito no Stage | Efeito no Working Directory | Efeito no Commit |
---|---|---|---|
--soft | Não afeta | Não afeta | Este tipo de reset desfaz o commit, mas mantém todas as alterações que estavam no Stage e no Working Directory, permitindo que você faça um novo commit com essas alterações ou as modifique antes de fazer um novo commit. |
--mixed | Desfaz | Mantém as alterações | Desfaz o commit e remove as alterações do Stage, mas mantém as alterações no Working Directory. Isso permite que você reavalie as alterações antes de adicioná-las novamente ao Stage e fazer um novo commit. |
--hard | Desfaz | Desfaz | Desfaz completamente o commit, removendo as alterações do Stage e do Working Directory. Tenha cuidado com esse tipo de reset, pois ele pode resultar na perda permanente de alterações não confirmadas. |
git reset
Como usar git reset
para desfazer commits locais
Uma vez tendo escolhido algum dos modos do git reset
na tabela anterior, agora é hora de realizar a operação, seguindo os exemplos abaixo:
# Exemplo com git reset --soft
git reset --soft HEAD~1
# Exemplo com git reset --mixed
git reset --mixed HEAD~1
# Exemplo com git reset --hard
git reset --hard HEAD~1
O que significa cada parte do git reset
:
Vamos pegar o comando abaixo e entender melhor o que cada parte significa:
git reset --soft HEAD~1
git reset
: Este é o comando principal que permite redefinir a posição do branch para um commit específico.
--soft
: Esta é uma opção que especifica o tipo de reset a ser realizado. O--soft
indica um reset suave, o que significa que o commit será desfeito, mas as alterações nos arquivos do commit serão mantidas na Stage (área de preparação).
HEAD~1
: Este é o argumento do comando que indica qual commit deve ser desfeito.HEAD
é uma referência ao commit mais recente no branch atual e~1
significa “um commit antes do HEAD“, ou seja, o commit imediatamente anterior.
Portanto, ao executar git reset --soft HEAD~1
, você desfaz o commit mais recente, mas mantém as alterações desse commit na Stage. Isso permite que você reavalie as alterações, faça modificações adicionais, se necessário, e crie um novo commit com as alterações revisadas.
Desfazendo commits locais usando o git revert
Uso do comando git revert
O comando git revert
é outra maneira de desfazer commits locais, mas de uma forma mais segura, pois cria um novo commit que desfaz as alterações do commit anterior.
Como o git revert
funciona
Vamos ver como usar o git revert
para desfazer commits locais e como ele cria um novo commit de reversão. Primeiramente, vamos ao comando:
git revert 4a3e2d1f4abef7d1c41e64d3f3e7fbb5a3b8e56d
Agora vamos entender como fica o histórico de commits antes e depois de usarmos o git revert
:
git log
antes do revert:
commit 4a3e2d1f4abef7d1c41e64d3f3e7fbb5a3b8e56d
Author: Pedro <pedro@codigo35.com>
Date: Ter Sep 20 15:30:45 2023 -0400
Adiciona funcionalidade de login
commit 2e1c8378d92e16449ff63cf69b86271b19f54a7d
Author: Pedro <pedro@codigo35.com>
Date: Sex Set 16 18:47:11 2023 -0400
Inicia projeto do site
git log
depois do revert:
commit c126fe85257d8c3c3f0657d9435375d75291e198
Author: Pedro <pedro@codigo35.com>
Date: Qua Set 21 10:45:18 2023 -0400
Revert 'Adiciona funcionalidade de login'
commit 4a3e2d1f4abef7d1c41e64d3f3e7fbb5a3b8e56d
Author: Pedro <pedro@codigo35.com>
Date: Ter Set 20 15:30:45 2023 -0400
Adiciona funcionalidade de login
commit 2e1c8378d92e16449ff63cf69b86271b19f54a7d
Author: Pedro <pedro@codigo35.com>
Date: Sex Set 16 18:47:11 2023 -0400
Inicia projeto do site
Boas práticas e dicas para commits no Git
Sugestões para evitar a necessidade de desfazer commits
Além de aprender a desfazer commits, é importante adotar práticas que minimizem a necessidade de fazê-lo 👀. Antes de mais nada, isso inclui fazer commits menores e mais frequentes, o que facilita a identificação de problemas e a colaboração com outros desenvolvedores.
Suponha que você esteja trabalhando em uma funcionalidade de autenticação para um aplicativo web. Em uma primeira abordagem, temos apenas commits grandes, como no exemplo abaixo:
1234ab Implementação da Autenticação
abcd123 Início do Projeto
Essa abordagem é ruim pois no commit 1234ab
(onde a funcionalidade é entregue) principalmente por temos muitas mudanças.
Esse tipo de abordagem aumenta a possibilidade de conflitos com códigos de outros desenvolvedores, ao mesmo tempo que é menos granular. Se você precisar reverter apenas parte das mudanças, terá que remover a funcionalidade toda.
Agora, em uma abordagem mais granular, observe a evolução da construção da funcionalidade através dos commits:
1234ab Correções de Bugs
wxyz789 Documentação
stuv456 Testes de Unidade
opqr123 Melhorias na Interface do Usuário
klmn890 Implementação do Logout
ghij567 Criação de Página de Perfil
cdef234 Implementação da Autenticação
yzab901 Criação de Rota de Login
uvwx678 Criação de Formulário de Login
qrst345 Criação de Rota de Registro
mnop012 Criação de Formulário de Registro
ijkl789 Configuração do Banco de Dados
efgh456 Criação de Páginas Iniciais
abcd123 Início do Projeto
Isso torna o histórico de commits mais claro e facilita a identificação de alterações específicas.
Utilização de mensagens de commit descritivas
Ao fazer commits, você deve adicionar mensagens descritivas que explicam o que você fez.
Mensagens de commit bem formuladas tornam o histórico do projeto mais compreensível e ajudam então a outros desenvolvedores a entender suas alterações. Veja um exemplo de uma mensagem de commit adequada:
git commit -m "Adiciona validação de formulário no processo de registro"
Nesse exemplo, a mensagem descreve claramente a natureza da alteração realizada no commit.
Além disso, existe a boa prática de prefixar suas mensagens de commit de maneira que se possa facilmente categorizar cada commit. Veja o mesmo exemplo acima usando prefixos:
git commit -m "feat: Adiciona validação de formulário no processo de registro"
Os prefixos mais comuns são:
Prefixo | Quando usar |
---|---|
feat | Usado para indicar que o commit adiciona uma nova funcionalidade ao projeto. |
fix | Indica que o commit corrige um bug ou problema existente no código. |
refactor | Usado quando o commit não adiciona novos recursos nem corrige bugs, mas realiza refatorações no código para melhorar a estrutura ou legibilidade. |
docs | Indica que o commit está relacionado à documentação do projeto, como atualizações na documentação de código, README ou guias do usuário. |
style | Usado para commits que se concentram em alterações de estilo, como formatação de código, espaçamento ou convenções de nomenclatura. |
test | Indica que o commit está relacionado a testes, como a adição de novos testes unitários, testes de integração ou correções em testes existentes. |
chore | Usado para commits que envolvem tarefas de manutenção ou pequenas alterações que não se enquadram nas categorias anteriores. |
revert | Indica que o commit é uma reversão de um commit anterior, geralmente referenciando o hash do commit revertido. |
Conclusão
Afinal, agora que você dominou as artes de desfazer commits no Git, está pronto para enfrentar o mundo do desenvolvimento de software com mais confiança. Sem dúvida, erros acontecem, mas com as ferramentas certas, como git reset
e git revert
, você pode corrigi-los rapidamente.
Continue explorando, pratique regularmente e nunca tenha medo de cometer erros. E lembre-se, estamos aqui para ajudar!
Links Uteis
- Documentação oficial do
git reset
- Documentação oficial do
git revert
- Thread do Stackoverflow sobre como desfazer commits (em inglês)
- Livro: Controlando Versões com Git e GitHub