git reflog

Esta página apresenta informações sobre o comando git reflog. O Git monitora as atualizações das pontas das ramificações com um mecanismo chamado logs de referência ou "reflogs". Muitos comandos do Git aceitam um parâmetro para especificar uma referência ou "ref", que é um indicador de um commit. Exemplos comuns incluem:

  • git checkout
  • git reset
  • git merge

Os reflogs monitoram quando referências do Git são atualizadas no repositório local. Além de reflogs de pontas de ramificações, é mantido um reflog especial para o Git stash. Os reflogs são armazenados em diretórios sob o diretório .git do repositório local. Os diretórios do git reflog podem ser encontrados em .git/logs/refs/heads/., .git/logs/HEAD e também .git/logs/refs/stash se o git stash tiver sido usado no repositório.

Falamos bastante sobre o git reflog na página Como reescrever o histórico. Este documento cobre: opções de configuração aprofundadas do git reflog, funções comuns e armadilhas do git reflog, como desfazer alterações com o git reflog, e mais.

Função básica

A função mais básica do Reflog é a invocação:

git reflog

Em resumo, é um atalho equivalente a:

git reflog show HEAD

Esse comando vai emitir o reflog do HEAD. Você vai visualizar algo como:

eff544f HEAD@{0}: commit: migrate existing content
bf871fd HEAD@{1}: commit: Add Git Reflog outline
9a4491f HEAD@{2}: checkout: moving from main to git_reflog
9a4491f HEAD@{3}: checkout: moving from Git_Config to main
39b159a HEAD@{4}: commit: expand on git context 
9b3aa71 HEAD@{5}: commit: more color clarification
f34388b HEAD@{6}: commit: expand on color support 
9962aed HEAD@{7}: commit: a git editor -> the Git editor

Visite a página Como escrever o histórico para ver outro exemplo de acessos comuns do reflog.

Referências do reflog

Por padrão, o git reflog vai gerar o reflog da referência do HEAD. O HEAD é uma referência simbólica à ramificação ativa no momento. Os reflogs também estão disponíveis para outras referências. A sintaxe para acessar uma referência do git é nome@{qualificador}. Além de referências do HEAD, outras ramificações, tags, remotos e o Git stash também podem ser referenciados.

Você pode obter um reflog completo de todas as referências ao executar:

  git reflog show --all 

Para ver o reflog de uma ramificação específica, transfira o nome dessa ramificação para git reflog show

 git reflog show otherbranch 9a4491f otherbranch@{0}: commit: seperate articles into branch PRs 35aee4a otherbranch{1}: commit (initial): initial commit add git-init and setting-up-a-repo docs 

A execução desse exemplo vai mostrar um reflog para a ramificação otherbranch. O exemplo a seguir presume que você já fez stash de algumas alterações com o comando git stash.

 git reflog stash 0d44de3 stash@{0}: WIP on git_reflog: c492574 flesh out intro 

Essa ação vai gerar um reflog do Git stash. Os indicadores de referência que retornaram podem ser transmitidos a outros comandos do Git:

 git diff stash@{0} otherbranch@{0} 

Quando executado, esse código de exemplo vai exibir os resultados do Git diff comparando as alterações de stash@{0} em relação à referência da otherbranch@{0}.

Reflogs temporizados

Todas as entradas de reflog têm um registro de tempo anexado. Esses registros podem ser aproveitados como o token qualificador da sintaxe do indicador de referência do Git. Ele permite que os reflogs do Git sejam filtrados pelo tempo. Os exemplos a seguir mostram qualificadores temporais disponíveis:

  • 1.minute.ago
  • 1.hour.ago
  • 1.day.ago
  • yesterday
  • 1.week.ago
  • 1.month.ago
  • 1.year.ago
  • 2011-05-17.09:00:00

Os qualificadores temporais podem ser combinados (por exemplo, 1.day.2.hours.ago), Formas no plural também são aceitas (por exemplo, 5.minutes.ago).

Referências de qualificadores temporais podem ser transmitidas a outros comandos do git.

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

Esse exemplo diferencia o branch principal atual do branch principal de 1 dia atrás. É muito útil se você quiser saber quais alterações ocorreram dentro de certo período.

Subcomandos e opções de configuração

O git reflog aceita alguns argumentos adicionais que são considerados subcomandos.

Show - git reflog show

A transmissão de show é implícita por padrão. Por exemplo, o comando:

 git reflog main@{0} 

equivale ao comando:

 git reflog show main@{0} 

Ainda, o git reflog show é um alias para git log -g --abbrev-commit --pretty=oneline. A execução do git reflog show vai exibir o log para o transmitido.

Expire - git reflog expire

O subcomando expire limpa entradas de reflog antigas ou inacessíveis. O subcomando expire pode acarretar perda de dados e não é usado com frequência pelos usuários finais, apenas pelo git em contexto interno. A execução de uma opção -n ou --dry-run para o git reflog expire vai realizar um "dry run" que vai exibir quais entradas de reflog estão marcadas para limpeza, mas não vai realizar a ação de fato.

Por padrão, o prazo de validade dos reflogs é de 90 dias. O prazo de validade pode ser definido pela transmissão de um argumento de linha de comando --expire=time para o git reflog expire ou pela definição de um nome de configuração do git para gc.reflogExpire.

Delete - git reflog delete

O subcomando delete é autoexplicativo e vai excluir uma entrada de reflog que foi transmitida. Assim como o expire, o delete pode acarretar perda de dados e não é invocado com frequência por usuários finais.

Como recuperar commits perdidos

O Git jamais perde algo, mesmo durante operações de reescrita de histórico como rebase ou correção de commits. Em relação ao próximo exemplo, faz de conta que a gente alterou algumas coisas no repositório. O git log --pretty=oneline está mais ou menos assim:

 338fbcb41de10f7f2e54095f5649426cb4bf2458 conteúdo expandido 1e63ceab309da94256db8fb1f35b1678fb74abd4 grupo de conteúdos c49257493a95185997c87e0bc3a9481715270086 definir intro eff544f986d270d7f97c77618314a06f024c7916 migrar conteúdo existente bf871fd762d8ef2e146d7f0226e81a92f91975ad Adicionar definição do Git Reflog 35aee4a4404c42128bee8468a9517418ed0eb3dc commit inicial adicionar git-init e documentos de configuração-de-um-repo 

Depois, a gente dá commit nessas alterações e executa o seguinte:

 #fazer alterações no HEAD git commit -am "algumas alterações de WIP" 

É mais ou menos assim que o log fica após a adição do commit novo:

 37656e19d4e4f1a9b419f57850c8f1974f871b07 algumas alterações de WIP 338fbcb41de10f7f2e54095f5649426cb4bf2458 conteúdo expandido 1e63ceab309da94256db8fb1f35b1678fb74abd4 grupo de conteúdos c49257493a95185997c87e0bc3a9481715270086 definir intro eff544f986d270d7f97c77618314a06f024c7916 migrar conteúdo existente bf871fd762d8ef2e146d7f0226e81a92f91975ad Adicionar definição do Git Reflog 35aee4a4404c42128bee8468a9517418ed0eb3dc commit inicial adicionar git-init e documentos de configuração-de-um-repo 

Nesse ponto, realizaremos um rebase interativo no branch principal por meio da execução de...

 git rebase -i origin/main 

Durante o rebase, os commits são marcados para squash com o subcomando s de rebase. Nesse processo, alguns commits passam por squash para o commit "algumas alterações de WIP" mais recente.

Devido ao squash dos commits, a definição do git log fica mais ou menos assim:

 40dhsoi37656e19d4e4f1a9b419f57850ch87dah987698hs algumas alterações de WIP 35aee4a4404c42128bee8468a9517418ed0eb3dc commit inicial adicionar git-inic e documentos de configuração-de-um-repo 

Analisando o git log nesse ponto, parece que os commits marcados para squash não existem mais. E se a gente quiser operar em um dos commits que passaram por squash? Talvez para excluir as alterações do histórico? É uma oportunidade para usar o reflog.

 git reflog 37656e1 HEAD@{0}: rebase -i (finalizar): retornando para refs/heads/git_reflog 37656e1 HEAD@{1}: rebase -i (iniciar): consultar origem/principal 37656e1 HEAD@{2}: commit: algumas alterações de WIP 

É possível ver que existem entradas de reflog para o início e o fim do rebase e o commit de "algumas alterações de WIP" antes delas. É possível transferir a referência do reflog para o git reset e redefinir para um commit que existia antes do rebase.

 git reset HEAD@{2} 

A execução desse comando de redefinição vai transferir o HEAD para o commit a que o "algumas alterações de WIP" foi adicionado, restaurando, em essência, os outros commits que passaram por squash.

Resumo

Neste tutorial, a gente falou sobre o comando git reflog. Alguns dos principais pontos apresentados foram:

  • Como visualizar o reflog de ramificações específicas
  • Como desfazer um rebase do git com o reflog
  • Como definir e visualizar entradas de reflog temporizadas

A gente mencionou que o git reflog pode ser usado com outros comandos do git, como o git checkout, git reset e o git merge. Saiba mais nas respectivas páginas. Para ver mais informações sobre referências e reflog, saiba mais aqui.

Pronto(a) para aprender Git?

Tente este tutorial interativo.

Comece agora mesmo