W3docs

git reflog

Saiba como usar o git reflog para recuperar commits perdidos, explorar referências e subcomandos, filtrar por tempo e ver exemplos práticos.

O comando git reflog é a sua rede de segurança. Ele registra todas as alterações feitas em referências locais — branches, HEAD e stashes — para que você possa recuperar commits que parecem ter desaparecido após um reset, rebase, amend ou exclusão de branch. Esta página explica o que o reflog armazena, como ler sua sintaxe name@{n}, como filtrar entradas por tempo, os subcomandos disponíveis e um passo a passo completo para recuperar commits "perdidos".

O que é o reflog

Uma referência (ou "ref") é um ponteiro para um commit — HEAD, a ponta de um branch como main, ou uma entrada de stash. Muitas operações do Git movem esses ponteiros: cada git commit, checkout, merge, rebase ou reset atualiza para onde uma ref aponta. O reflog ("reference log") registra esse histórico de movimentos.

Isso é importante porque o Git quase nunca exclui commits imediatamente. Quando uma operação como um hard reset ou um rebase torna um commit inacessível a partir de qualquer branch ou tag, o objeto de commit ainda existe no repositório e o reflog ainda mantém um ponteiro para ele. Enquanto essa entrada do reflog existir, você pode recuperar o commit.

git reflog

Informação

O reflog é estritamente local e por clone. Ele nunca é enviado via push ou recebido via fetch, portanto um clone recente tem um reflog vazio. Se você reescrever o histórico e perder um commit, só é possível recuperá-lo na máquina onde o trabalho foi realizado.

Uso básico

A forma mais simples não recebe argumentos:

git reflog

Isso é um atalho para exibir o reflog de HEAD:

git reflog show HEAD

A saída lista cada posição que HEAD ocupou, da mais recente para a mais antiga:

a32556a HEAD@{0}: commit: migrating content
ab371fd HEAD@{1}: commit: adding git reflog outline
23a491a HEAD@{2}: checkout: moving from stage to feature/solver
7b119cb HEAD@{3}: checkout: moving from feature/solver to stage
56a183a HEAD@{4}: commit: changing color scheme
7a2aa71 HEAD@{5}: commit: adding more color palettes
a56322b HEAD@{6}: commit: adding color tool package

Leia cada linha como três partes:

  • a32556a — o hash abreviado do commit para o qual HEAD apontava.
  • HEAD@{0} — o seletor do reflog. @{0} é a posição mais recente, @{1} a anterior, e assim por diante, contando de trás para frente no tempo.
  • commit: migrating content — a ação que moveu a ref, junto com sua mensagem.

O rótulo da ação informa como a ref foi movida (commit, checkout, merge, rebase -i, reset), o que torna o reflog legível como um histórico passo a passo do que você fez localmente.

Referências do reflog

Por padrão, o git reflog exibe o reflog de HEAD, que acompanha qualquer branch que esteja atualmente em checkout. Mas toda ref mantém seu próprio reflog, e você acessa qualquer um deles com a sintaxe name@{qualifier}.

Para ver o reflog de todas as referências de uma vez:

git reflog show --all

Passe um nome de branch para inspecionar apenas o histórico daquele branch. Abaixo, o reflog para test_branch:

git reflog show test_branch
32a591f test_branch@{0}: commit: add snippets
23bae4a test_branch@{1}: commit (initial): initial commit

Observe a diferença: HEAD@{1} significa "onde HEAD estava um movimento atrás," enquanto test_branch@{1} significa "onde o próprio test_branch estava um movimento atrás." Essa distinção é o que permite recuperar a ponta de um branch que um hard reset ou uma atualização forçada moveu.

Você também pode ler o reflog do git stash:

git reflog stash
0d44de3 stash@{0}: WIP on git_reflog: a567574 adding Vue.js

Reflogs com filtro de tempo

Cada entrada do reflog possui um timestamp associado. Eles podem ser usados como qualificadores na sintaxe de ponteiro de ref do Git, permitindo filtrar os reflogs por tempo. Veja alguns exemplos de qualificadores de tempo:

  • 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

Você pode combinar qualificadores (por exemplo, 1.week.3.hours.ago) e usar formas no plural (por exemplo, 5.hours.ago). Uma ref qualificada por tempo pode ser passada para outros comandos do Git, não apenas para o git reflog:

git diff master@{0} master@{1.week.ago}

Isso exibe um diff do master atual em relação a onde master apontava há uma semana.

Aviso

Um qualificador de tempo é resolvido em relação ao reflog, não às datas de commit. master@{1.week.ago} significa "o commit ao qual master fazia referência há uma semana nesta máquina," o que pode ser diferente de "o commit criado há uma semana." Em um clone recente sem histórico de reflog, o Git usa a ponta atual como fallback e pode avisar que o log é curto demais.

Subcomandos do git reflog

O git reflog aceita vários argumentos que funcionam como subcomandos. Eles são descritos abaixo.

git reflog show

git reflog show é o comportamento padrão e é um alias para git log -g --abbrev-commit --pretty=oneline. Esses dois comandos são equivalentes:

git reflog master@{0}
git reflog show master@{0}

git reflog expire

git reflog expire remove entradas antigas ou inacessíveis do reflog. Como a remoção de entradas pode tornar commits genuinamente irrecuperáveis, raramente se executa esse comando manualmente — o Git o executa automaticamente durante o git gc. Por padrão, entradas acessíveis expiram após 90 dias (gc.reflogExpire) e as inacessíveis após 30 dias (gc.reflogExpireUnreachable). Para forçar uma expiração personalizada:

git reflog expire --expire=1.day.ago --all

git reflog delete

git reflog delete remove uma entrada específica do reflog pelo seu seletor. Assim como o expire, ele apresenta um risco real de perda de recuperabilidade e raramente é necessário no trabalho cotidiano:

git reflog delete HEAD@{1}
Perigo

Assim que uma entrada do reflog expirar ou for excluída, o commit ao qual ela apontava torna-se verdadeiramente inacessível e será removido na próxima vez que git gc for executado. Trate expire e delete como ferramentas de limpeza, não como ferramentas de desfazer.

Recuperando commits perdidos

Os commits nunca são verdadeiramente perdidos no Git, mesmo durante operações de reescrita de histórico — e o reflog é a maneira de recuperá-los. Suponha que git log --pretty=oneline exiba o seguinte:

2b43ceab309da94256db8fb1f35b1678fb74abd4 changes in content
c32557493a95185997c87e0bc3a9481715279351 adding Vue.js
abc234f986d270d7f97c77618314a06f024c4563 migrating content
a5673cd762d8ef2e146d7f0226e81a92f91956b1 adding git reflog outline
2bce4a4404c42128bee8468a9517418ed0ea412 initial commit

Agora suponha que fazemos o commit de algumas alterações novas neste repositório:

# make changes to HEAD
git commit -am "API changes"

O log agora tem a seguinte aparência:

37656e19d4e4f1a9b419f57850c8f1974f871b07 API changes
2b43ceab309da94256db8fb1f35b1678fb74abd4 changes in content
c32557493a95185997c87e0bc3a9481715279351 adding Vue.js
abc234f986d270d7f97c77618314a06f024c4563 migrating content
a5673cd762d8ef2e146d7f0226e81a92f91956b1 adding git reflog outline
2bce4a4404c42128bee8468a9517418ed0ea412 initial commit

Em seguida, iniciamos um rebase interativo em relação ao master:

git rebase -i origin/master

Durante o rebase, marcamos os commits com a ação s (squash) para mesclá-los ao commit mais recente de "API changes". Após isso, a saída do git log fica reduzida a:

40d8a1237656e19d4e4f1a9b419f57850c8f1974 API changes
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit

Os commits mesclados parecem ter desaparecido. Mas o reflog ainda registra cada posição que HEAD ocupou durante o rebase:

git reflog
37656e1 HEAD@{0}: rebase -i (finish): returning to refs/heads/git_reflog
37656e1 HEAD@{1}: rebase -i (start): checkout origin/master
37656e1 HEAD@{2}: commit: API changes

HEAD@{2} é o estado imediatamente antes do rebase começar. Passe esse seletor para o git reset para retornar a ele:

git reset --hard HEAD@{2}

Isso move HEAD de volta para o commit "API changes" anterior ao rebase e restaura todos os commits mesclados. Use --hard para também redefinir a árvore de trabalho para esse estado, ou omita-o (git reset HEAD@{2}) para mover apenas o ponteiro do branch mantendo os arquivos atuais.

Quando usar o git reflog

Recorra ao reflog sempre que uma ref tiver sido movida e você quiser recuperá-la:

  • Após um git reset --hard que descartou commits que você realmente precisava.
  • Para recuperar commits órfãos por um rebase interativo, amend ou squash.
  • Para restaurar um branch excluído com git branch -D (encontre sua última ponta no reflog e depois execute git branch <name> <hash>).
  • Para descobrir onde HEAD estava antes de uma série confusa de checkouts ou merges.

Se o commit for mais recente do que a janela de expiração do reflog (90 dias para entradas acessíveis por padrão), ele é recuperável.

Páginas relacionadas

  • git reset — mova refs para uma entrada do reflog para desfazer alterações.
  • git rebase — a operação de reescrita que o reflog mais frequentemente resgata.
  • git stash — os stashes têm seu próprio reflog em stash@{n}.
  • git log — a visualização de histórico padrão; git log -g lê o reflog.

Prática

Prática
Quais são as afirmações corretas sobre o comando `git reflog`?
Quais são as afirmações corretas sobre o comando `git reflog`?
Was this page helpful?