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 <ref>

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 registro de referências da referência do HEAD. O HEAD é uma referência simbólica à ramificação ativa no momento. Os registros de referências também estão disponíveis para outras referências. A sintaxe para acessar uma referência do git é name@{qualifier}. 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

O Bitbucket exibe a página Criar um novo repositório. Dedique alguns momentos para rever o conteúdo da caixa de diálogo. Com exceção do Tipo de repositório, tudo que você inserir nessa página pode ser alterado mais tarde.

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. Executar git reflog show <refid> vai exibir o log do <refid> passado.

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 extended content
1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content
c49257493a95185997c87e0bc3a9481715270086 flesh out intro
eff544f986d270d7f97c77618314a06f024c7916 migrate existing content
bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs

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

#make changes to HEAD
git commit -am "some WIP changes"

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

$ git clone

https://emmap1@bitbucket.org/emmap1/bitbucketstationlocations.git 

Cloning into 'bitbucketspacestation'...

fatal: could not read

Password for 'https://emmap1@bitbucket.org': No such file or directory

Se esse erro for exibido, digite o seguinte na linha de comando:

37656e19d4e4f1a9b419f57850c8f1974f871b07 some WIP changes
338fbcb41de10f7f2e54095f5649426cb4bf2458 extended content
1e63ceab309da94256db8fb1f35b1678fb74abd4 bunch of content
c49257493a95185997c87e0bc3a9481715270086 flesh out intro
eff544f986d270d7f97c77618314a06f024c7916 migrate existing content
bf871fd762d8ef2e146d7f0226e81a92f91975ad Add Git Reflog outline
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs

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 some WIP changes
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit add git-init and setting-up-a-repo docs

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 (finish): returning to refs/heads/git_reflog
37656e1 HEAD@{1}: rebase -i (start): checkout origin/main
37656e1 HEAD@{2}: commit: some WIP changes

É 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.

Recomendado para você

Blog do Bitbucket

Caminho de aprendizagem de DevOps

Saiba mais sobre o Git

Encontre mais guias e recursos de Git neste hub.