Git Reflog: Compreensão e Utilização de 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 era essa a intenção. Por isso, estou feliz em compartilhar algo que aprendi através da minha própria experiência e que gostaria de ter aprendido mais cedo, que é como usar git reflog. git reflog é uma daquelas técnicas que definitivamente valem a pena aprender; se você dedicar um pouco de tempo agora, pode evitar uma grande dor de cabeça no futuro.

Embora eu vá mostrar o git reflog, que considero muito útil para navegar e recuperar de erros, também quero recomendar nossos cursos Foundations of Git e Introduction to GitHub Concepts para aprender tudo o 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 branches e a referência HEAD em um repositório Git. (No contexto do Git, HEAD refere-se 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 na ancestralidade, mostrando como os commits estão conectados em um branch, git reflog captura todos os movimentos da HEAD, incluindo trocas de branches, rebases, redefinições e commits. Isso torna o reflog útil para recuperar commits perdidos e depurar ações recentes.

Quando são criadas as entradas no reflog?

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:

  • Realizar alterações usando git commit.

  • Fazer checkout de um branch diferente usando git checkout nome_branch.

  • Criar um novo branch usando git branch novo_branch.

  • Rebasing git rebase

  • Reverter 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 do 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 troca para o ramo HEAD.

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

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

Cada entrada mostra:

  • O hash do commit (fa82776)

  • O índice do 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 os estados anteriores do seu repositório. Ao entender como navegar nas entradas do reflog, você pode recuperar commits perdidos, desfazer alterações e comparar versões passadas 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 git reflog serve como um registro de atualizações de referência anteriores, permitindo-nos localizar e restaurar pontos anteriores na história do nosso repositório. Sem ele, essas referências não existiriam e precisaríamos de hashes de commit exatos 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 mudanças passadas. Imagem do 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 mudanças 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 dos 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 carimbo de data e hora 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 esses dois instantâneos.

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 em que 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 na saída do reflog e verifique-o:

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 malfeiro

Se um rebase der errado, você pode usar git reflog para encontrar o commit antes do rebase e redefinir seu branch. Identifique o commit anterior ao 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ê deletar um branch acidentalmente, você 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 anterior de stash, use o seguinte comando:

git stash apply stash@{2}

Confira o 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 análise estruturada dos principais subcomandos do git reflog e seu uso.

git reflog show: Mostra as entradas de 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 a 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 as antigas entradas de reflog que excedem o limite de tempo especificado. Por exemplo, o seguinte comando remove entradas com mais de 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 exists <ref>: Verifica se existe um reflog para uma referência específica. Por exemplo, o comando abaixo retorna sucesso se o ramo principal tiver um reflog.

git reflog exists main

Opções para subcomandos git reflog

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

--expire-unreachable=<time>: Limpa apenas as entradas de reflog que são inalcançáveis a partir de qualquer ref. Por exemplo, o comando abaixo remove entradas de reflog inalcançá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 para HEAD. O comando abaixo limpa todos os reflogs mais antigos que 60 dias em todos os ramos.

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 entradas antigas 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 de 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, ramos e stashes, incluindo ações como trocas de ramo, resets, rebases e mais. Ele rastreia mudanças que podem não fazer parte da ancestralidade do commit.

  • git reflog é estritamente local em 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 remotamente Sim Não
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 seguir ao trabalhar com o reflog.

  • Usar Reflog para Recuperação e Depuração: Se você redefiniu 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 se algo der 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 lixo e se tornarem irrecuperáveis. Faça push regularmente de seus commits para um repositório remoto para garantir que eles sejam preservados além do reflog local.

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

Conclusão

O gerenciamento eficaz do histórico de um projeto no Git requer mais do que 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 excluídas e corrigir erros. Ganhar 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. Com isso em mente, recomendo estudar nossa postagem 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