Git Reflog: Compreendendo e Usando Logs de Referência no Git

Não há nada mais irritante para um desenvolvedor ou engenheiro de dados do que deletar acidentalmente branches do git ou redefinir commits quando não se queria. Por isso, estou feliz em compartilhar algo que aprendi através da minha própria experiência e gostaria de ter aprendido mais cedo, que é como usar git reflog. git reflog é uma daquelas técnicas que definitivamente valem a pena ser aprendidas; se você dedicar um pouco de tempo agora, pode evitar muita dor de cabeça no futuro.

Enquanto estarei mostrando a você git reflog, que acho muito útil para navegar e se recuperar de erros, também quero recomendar nossos cursos Princípios do Git e Introdução aos Conceitos do GitHub para aprender tudo que há para saber sobre controle de versão.

O que é git reflog?

O git reflog, ou registro de referências, é um mecanismo de rastreamento local que registra as atualizações das pontas de branch e da referência HEAD em um repositório Git. (No contexto do Git, HEAD se refere ao commit atual em que seu diretório de trabalho e área de preparação estão baseados.)

Ao contrário do git log, que exibe o histórico de commits com base em ancestralidade, mostrando como os commits estão conectados em um branch, o git reflog captura todos os movimentos do HEAD, incluindo trocas de branch, rebases, resets e commits. Isso torna o reflog útil para recuperar commits perdidos e depurar ações recentes.

Quando as entradas do reflog são criadas?

As entradas do reflog são criadas sempre que você realiza ações que alteram o estado de HEAD ou referências de branches. Cenários comuns incluem os seguintes:

  • Confirmar alterações usando git commit.

  • Comutar para um branch diferente usando git checkout nome_do_branch.

  • Criar um novo branch usando git branch novo_branch.

  • Rebasing git rebase

  • Redefinir para um commit anterior git reset --hard.

  • Realizar o merge de branches usando git merge.

Aqui está o código que você usa para rastrear atualizações no repositório local:

git reflog

Usando git reflog para rastrear atualizações no repositório local. Imagem por Autor.

Como você interpreta a saída do git reflog?

Você pode interpretar a saída da seguinte forma:

  • HEAD@{0}: A ação mais recente foi a mudança para o branch HEAD.

  • HEAD@{1}: Antes disso, eu havia alterado um arquivo de .xlxs para o formato .csv.

  • HEAD@{2}: Fiz o primeiro commit ao enviar os arquivos para o repositório.

Cada entrada mostra:

  • O hash do commit (fa82776)

  • O índice reflog (HEAD@{0}, HEAD@{1}, etc.)

  • Uma descrição da ação realizada (commit, checkout, rebase)

Como usar o git reflog

O Git reflog fornece uma maneira de rastrear atualizações de referência e restaurar estados anteriores do seu repositório. Ao entender como navegar pelas entradas do reflog, você pode recuperar commits perdidos, desfazer alterações e comparar versões anteriores do seu trabalho.

Comando básico do git reflog

Abaixo está o comando básico do reflog:

git reflog

O comando acima exibe uma lista de ações recentes que atualizaram o HEAD ou referências de branches, incluindo commits, trocas de branches, resets, rebases e mais. Cada entrada é indexada, como HEAD@{0} e HEAD@{1}, para representar sua posição no histórico do reflog.

Referenciando estados passados

O reflog do Git serve como um registro de atualizações de referência passadas, permitindo-nos localizar e restaurar pontos anteriores na história de nosso repositório. Sem ele, essas referências não existiriam, e precisaríamos de hashes exatos de commit para retornar a estados passados específicos. Agora, vamos explorar como o Git nos permite navegar por esses estados passados usando git checkout.

HEAD@{n}: Refere-se a uma entrada específica do reflog, onde n é o índice. Por exemplo, HEAD@{2} refere-se ao terceiro estado mais recente de HEAD.

git checkout HEAD@{2}

Usando o git checkout para rastrear alterações passadas. Imagem por Autor.

branch@{time}: Refere-se ao estado de um ramo em um momento específico. Por exemplo, main@{1.week.ago} refere-se ao estado do ramo principal uma semana atrás, enquanto feature@{yesterday} refere-se ao estado do ramo de funcionalidade ontem.

git checkout main@{1.week.ago}

Usando git checkout para rastrear alterações passadas. Imagem por Autor.

Qualificadores baseados em tempo

git reflog não apenas nos ajuda a restaurar estados passados, mas também nos permite compará-los. Como o reflog rastreia atualizações de referência, podemos usá-lo para ver como nosso repositório mudou ao longo do tempo. Agora, vamos ver como o git diff utiliza entradas do reflog para comparar estados passados e presentes.

Os exemplos a seguir são de qualificadores de tempo que facilitam a restauração do seu repositório para um ponto específico no tempo, em vez de depender apenas de números de índice do reflog.

git checkout HEAD@{1.minute.ago} # Estado de um minuto atrás
git checkout HEAD@{1.hour.ago} # Estado de uma hora atrás
git checkout HEAD@{1.week.ago} # Estado de uma semana atrás
git checkout HEAD@{yesterday} # Estado de ontem
git checkout HEAD@{2024-01-01.12:00:00} # Estado em um horário específico

Comparando estados passados com git diff

Você pode comparar estados passados usando comandos como git diff. O comando a seguir compara o estado atual do ramo principal main@{0} com seu estado de um dia atrás, main@{1.day.ago}. A saída mostrará quaisquer diferenças entre essas duas capturas.

git diff main@{0} main@{1.day.ago}

Comparando estados passados com git diff. Imagem por Autor.

Casos de uso comuns para Git Reflog

O reflog do Git é uma ferramenta inestimável para recuperar alterações perdidas, desfazer erros e corrigir problemas comuns do Git. Abaixo estão alguns cenários práticos onde git reflog pode ajudar.

Desfazendo um reset ruim

Se você redefiniu acidentalmente seu ramo usando git reset --hard, você pode usar o reflog para restaurar seu estado anterior.

git reset --hard HEAD@{3}

Recuperando commits perdidos

Se você deletar acidentalmente um branch ou perder commits devido a um reset ou rebase, você pode encontrar o commit perdido usando git reflog.

git reflog

Localize o hash do commit a partir da saída do reflog e confira:

git checkout <commit-hash>

Depois de verificar o commit perdido, você pode criar um novo branch para preservá-lo:

git branch recovered-branch <commit-hash>

Corrigindo um rebase malfeito

Se um rebase der errado, você pode usar git reflog para encontrar o commit antes do rebase e redefinir seu branch. Identifique o commit antes do rebase e redefina-o.

git reset --hard HEAD@{3} # Ajuste o número com base na saída do reflog

Restaurando um branch deletado

Se você deletou um branch acidentalmente, pode recuperá-lo usando git reflog. Encontre o último commit conhecido do branch deletado e recrie-o:

git branch restored-branch <commit-hash>

Rastreando o histórico do stash

O git reflog também pode ser usado para visualizar o histórico do stash. O comando abaixo lista as operações do stash, permitindo que você recupere stashes mais antigos, se necessário.

git reflog stash

Para aplicar uma entrada de stash anterior, use o seguinte comando:

git stash apply stash@{2}

Confira nosso tutorial Git Pull Force: Como Sobrescrever um Branch Local com o Remoto para aprender as melhores práticas para sobrescrever alterações locais.

Subcomandos e opções do Git Reflog

O Git fornece vários subcomandos e opções para gerenciar e interagir com reflogs.

Subcomandos do Git reflog

Abaixo está uma divisão estruturada dos principais subcomandos do git reflog e seu uso.

git reflog show: Exibe as entradas do reflog para HEAD por padrão ou para uma referência especificada, como um branch.

git reflog show

Usando git reflog show para exibir entradas para referência especificada. Imagem por Autor.

git reflog list: Este comando exibe todas as referências com um reflog. É útil para identificar ramos e referências HEAD com entradas de reflog armazenadas.

git reflog list

git reflog delete <ref>@{<specifier>}: Limpa antigas entradas de reflog que excedem o limite de tempo especificado. Por exemplo, o comando a seguir remove entradas mais antigas do que 30 dias.

git reflog expire --expire=30.days.ago

git reflog delete <ref>@{<specifier>}: Exclui uma entrada de reflog específica com base em sua referência e posição. O comando abaixo remove a entrada de reflog no índice 2 para HEAD.

git reflog delete HEAD@{2}

git reflog existe <ref>: Verifica se existe um reflog para uma referência específica. Por exemplo, o comando abaixo retorna sucesso se o branch principal tiver um reflog.

git reflog exists main

Opções para subcomandos do git reflog

As seguintes são as opções disponíveis para os subcomandos do git reflog e seus usos.

--expire-unreachable=<time>: Podar apenas as entradas de reflog que são inacessíveis a partir de qualquer ref. Por exemplo, o comando abaixo remove entradas de reflog inacessíveis mais antigas que 7 dias.

git reflog expire --expire-unreachable=7.days.ago

--all: Processa reflogs para todas as referências, não apenas HEAD. O comando abaixo limpa todos os reflogs mais antigos que 60 dias em todos os branches.

git reflog expire --expire=60.days.ago --all

--dry-run: Simula a execução de um comando, mostrando o que seria podado sem realmente excluir nada. Por exemplo, o comando abaixo exibe quais entradas seriam removidas.

git reflog expire --expire=30.days.ago --dry-run

--verbose: Fornece uma saída detalhada sobre as ações realizadas pelo comando. O comando abaixo mostra detalhes verbosos ao expirar antigas entradas de reflog.

git reflog expire --expire=90.days.ago --verbose

Git Reflog vs. Git Log: Diferenças Chave

Ambos git log e git reflog fornecem insights sobre a história de um repositório, mas servem para propósitos diferentes. Vamos analisar essas diferenças para entender como cada um pode ser usado para controle de versão e estratégias de recuperação.

  • git log mostra o histórico de commits seguindo a ancestralidade dos commits em um ramo. Ele fornece uma visão cronológica de como o conteúdo do repositório evoluiu.

  • git reflog registra atualizações em referências como HEAD, branches e stashes, incluindo ações como trocas de branch, resets, rebases e mais. Ele rastreia mudanças que podem não fazer parte da ancestralidade de commits.

  • git reflog é estritamente local à sua máquina e não é compartilhado com repositórios remotos.

  • Enquanto git log não pode recuperar commits que não fazem mais parte da ancestralidade do ramo, git reflog pode ajudar a recuperar commits “perdidos” rastreando atualizações de referência, mesmo que esses commits não sejam mais alcançáveis a partir de nenhum ramo.

A tabela abaixo resume essas diferenças-chave.

Feature git log git reflog
Rastreia commits Sim Não
Rastreia atualizações de referência Não Sim
Compartilhado em remoto Sim Não
Você pode recuperar commits perdidos Não Sim

Melhores Práticas para Usar o Git Reflog

O reflog do Git é uma ferramenta poderosa para recuperar commits perdidos e corrigir problemas de histórico, mas usá-lo efetivamente requer cautela. Aqui estão algumas melhores práticas a serem seguidas ao trabalhar com o reflog.

  • Use o Reflog para Recuperação e Depuração: Se você resetou ou refez um branch incorretamente por acidente, verifique o git reflog para encontrar uma referência anterior e restaurá-la.

  • Tenha cuidado com git reset --hard: git reset --hard pode remover permanentemente alterações não confirmadas. Sempre verifique o reflog primeiro para garantir que você possa recuperar caso algo dê errado.

  • Faça backups antes de executar comandos destrutivos: Para proteger contra a perda de dados, implemente backups automatizados de seus repositórios Git. Sempre armazene os backups em um local seguro e externo para garantir a recuperabilidade em caso de falha de hardware ou outros desastres.

  • Não confie apenas no Reflog para recuperação de longo prazo:Por padrão, as entradas do reflog são mantidas por 90 dias. Após esse período, elas podem ser coletadas pelo coletor de lixo e se tornarem irreversíveis. Envie regularmente seus commits para um repositório remoto para garantir que eles sejam preservados além do seu reflog local.

  • Use git reflog expire para Gerenciar Entradas Antigas: Se o reflog do seu repositório estiver desorganizado, limpe as entradas antigas ou inacessíveis usando git reflog expire.

Conclusão

Gerenciar efetivamente o histórico de um projeto no Git requer mais do que apenas comandos básicos. Explorar ferramentas avançadas que rastreiam atualizações de referência pode fornecer uma rede de segurança valiosa para recuperar commits perdidos, restaurar branches deletadas e corrigir erros. Obter experiência prática com essas ferramentas, juntamente com comandos como git reset, git checkout e git revert, pode melhorar significativamente sua proficiência em controle de versão.

Fazer nossos cursos não é apenas uma ótima maneira de aprender, mas também uma ótima maneira de sinalizar aos empregadores que você leva o desenvolvimento de software a sério. Nesse sentido, recomendo estudar nosso post no blog Top 20 Perguntas e Respostas de Entrevista do Git para Todos os Níveis e fazer nossa nova trilha de habilidades Git Fundamentals para se tornar um especialista em tudo relacionado ao Git.

Source:
https://www.datacamp.com/tutorial/git-reflog