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