git reflog
Подробная информация о команде git reflog: ссылки и подкоманды рефлога, фильтрация по времени и примеры восстановления коммитов.
Команда git reflog — это ваша страховочная сеть. Она фиксирует каждое изменение локальных ссылок — веток, HEAD и стешей — чтобы вы могли восстановить коммиты, которые, казалось бы, исчезли после сброса, перебазирования, изменения или удаления ветки. На этой странице объясняется, что хранит рефлог, как читать синтаксис name@{n}, как фильтровать записи по времени, какие подкоманды доступны, и приводится полное руководство по восстановлению «потерянных» коммитов.
Что такое рефлог
Ссылка (или «ref») — это указатель на коммит: HEAD, вершина ветки вроде main или запись стеша. Многие операции Git перемещают эти указатели: каждый git commit, checkout, merge, rebase или reset обновляет то, на что указывает ссылка. Рефлог («журнал ссылок») фиксирует историю этих перемещений.
Это важно, потому что Git почти никогда не удаляет коммиты немедленно. Когда операция — например, жёсткий сброс или перебазирование — делает коммит недостижимым из любой ветки или тега, объект коммита по-прежнему остаётся в репозитории, а рефлог сохраняет на него указатель. Пока эта запись в рефлоге существует, коммит можно вернуть.

Рефлог строго локален и принадлежит конкретному клону. Он никогда не передаётся при push или fetch, поэтому свежий клон имеет пустой рефлог. Если вы переписали историю и потеряли коммит, восстановить его можно только на той машине, где была выполнена эта работа.
Базовое использование
Простейшая форма не требует аргументов:
git reflogЭто сокращение для отображения рефлога HEAD:
git reflog show HEADВ выводе перечисляются все позиции HEAD, начиная с самой новой:
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Каждую строку можно разбить на три части:
a32556a— сокращённый хеш коммита, на который указывалHEAD.HEAD@{0}— селектор рефлога.@{0}— самая последняя позиция,@{1}— предыдущая, и так далее в обратном хронологическом порядке.commit: migrating content— действие, переместившее ссылку, и его сообщение.
Метка действия говорит о том, как переместилась ссылка (commit, checkout, merge, rebase -i, reset), что делает рефлог читаемым пошаговым журналом того, что вы делали локально.
Ссылки рефлога
По умолчанию git reflog показывает рефлог HEAD, который следует за текущей активной веткой. Но каждая ссылка ведёт собственный рефлог, и обратиться к любому из них можно с помощью синтаксиса name@{qualifier}.
Чтобы увидеть рефлог всех ссылок сразу:
git reflog show --allПередайте имя ветки, чтобы просмотреть только её историю. Ниже — рефлог для test_branch:
git reflog show test_branch
32a591f test_branch@{0}: commit: add snippets
23bae4a test_branch@{1}: commit (initial): initial commitОбратите внимание на разницу: HEAD@{1} означает «где находился HEAD одно перемещение назад», тогда как test_branch@{1} означает «где находилась сама test_branch одно перемещение назад». Это различие позволяет восстановить вершину ветки, которую переместил жёсткий сброс или принудительное обновление.
Также можно просмотреть рефлог для git stash:
git reflog stash
0d44de3 stash@{0}: WIP on git_reflog: a567574 adding Vue.jsРефлог с фильтрацией по времени
К каждой записи рефлога прикреплена метка времени. Её можно использовать как квалификатор в синтаксисе указателей ссылок Git, что позволяет фильтровать рефлоги по времени. Вот несколько примеров временных квалификаторов:
- 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
Квалификаторы можно комбинировать (например, 1.week.3.hours.ago) и использовать во множественном числе (например, 5.hours.ago). Ссылка с временным квалификатором может передаваться другим командам Git, а не только git reflog:
git diff master@{0} master@{1.week.ago}Это покажет diff текущего состояния master относительно того, где master находился неделю назад.
Временной квалификатор разрешается по рефлогу, а не по датам коммитов. master@{1.week.ago} означает «коммит, на который указывал master неделю назад на этой машине», что может отличаться от «коммита, созданного неделю назад». На свежем клоне без истории рефлога Git вернётся к текущей вершине и может предупредить, что журнал слишком короткий.
Подкоманды git reflog
Git reflog принимает несколько аргументов, действующих как подкоманды. Они описаны ниже.
git reflog show
git reflog show — поведение по умолчанию, и сама по себе эта команда является псевдонимом для git log -g --abbrev-commit --pretty=oneline. Следующие две команды эквивалентны:
git reflog master@{0}
git reflog show master@{0}git reflog expire
git reflog expire удаляет старые или недостижимые записи рефлога. Поскольку удаление записей может сделать коммиты по-настоящему невосстановимыми, вы редко запускаете эту команду вручную — Git запускает её автоматически во время git gc. По умолчанию достижимые записи истекают через 90 дней (gc.reflogExpire), а недостижимые — через 30 дней (gc.reflogExpireUnreachable). Чтобы задать произвольное время истечения:
git reflog expire --expire=1.day.ago --allgit reflog delete
git reflog delete удаляет одну конкретную запись рефлога по её селектору. Как и expire, это несёт реальный риск потери возможности восстановления и редко требуется в повседневной работе:
git reflog delete HEAD@{1}После того как запись рефлога истекает или удаляется, коммит, на который она указывала, становится по-настоящему недостижимым и будет удалён при следующем запуске git gc. Используйте expire и delete как инструменты очистки, а не отмены действий.
Восстановление потерянных коммитов
В Git коммиты никогда по-настоящему не теряются, даже после операций переписывания истории — и рефлог позволяет их вернуть. Предположим, git log --pretty=oneline выглядит так:
2b43ceab309da94256db8fb1f35b1678fb74abd4 changes in content
c32557493a95185997c87e0bc3a9481715279351 adding Vue.js
abc234f986d270d7f97c77618314a06f024c4563 migrating content
a5673cd762d8ef2e146d7f0226e81a92f91956b1 adding git reflog outline
2bce4a4404c42128bee8468a9517418ed0ea412 initial commitТеперь предположим, что мы делаем новые изменения в этом репозитории:
# make changes to HEAD
git commit -am "API changes"Теперь лог выглядит так:
37656e19d4e4f1a9b419f57850c8f1974f871b07 API changes
2b43ceab309da94256db8fb1f35b1678fb74abd4 changes in content
c32557493a95185997c87e0bc3a9481715279351 adding Vue.js
abc234f986d270d7f97c77618314a06f024c4563 migrating content
a5673cd762d8ef2e146d7f0226e81a92f91956b1 adding git reflog outline
2bce4a4404c42128bee8468a9517418ed0ea412 initial commitЗатем мы запускаем интерактивное перебазирование относительно master:
git rebase -i origin/masterВ процессе перебазирования мы помечаем коммиты действием s (squash), чтобы объединить их в самый последний коммит «API changes». После этого вывод git log сворачивается до:
40d8a1237656e19d4e4f1a9b419f57850c8f1974 API changes
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commitОбъединённые коммиты кажутся исчезнувшими. Но рефлог по-прежнему фиксирует каждую позицию HEAD во время перебазирования:
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 changesHEAD@{2} — это состояние непосредственно перед началом перебазирования. Передайте этот селектор команде git reset, чтобы вернуться к нему:
git reset --hard HEAD@{2}Это перемещает HEAD обратно к коммиту «API changes», существовавшему до перебазирования, и восстанавливает все объединённые коммиты. Используйте --hard, чтобы также сбросить рабочее дерево к этому состоянию, или опустите флаг (git reset HEAD@{2}), чтобы переместить только указатель ветки, сохранив текущие файлы.
Когда использовать git reflog
Обращайтесь к рефлогу всякий раз, когда ссылка переместилась и вы хотите её вернуть:
- После
git reset --hard, который отбросил нужные вам коммиты. - Для восстановления коммитов, ставших недостижимыми после интерактивного перебазирования, амендмента или объединения.
- Чтобы восстановить ветку, удалённую с помощью
git branch -D(найдите её последнюю вершину в рефлоге, затем выполнитеgit branch <name> <hash>). - Чтобы найти, где находился
HEADдо запутанной серии переключений или слияний.
Если коммит моложе окна истечения рефлога (по умолчанию 90 дней для достижимых записей), его можно восстановить.
Связанные страницы
- git reset — перемещение ссылок на запись рефлога для отмены изменений.
- git rebase — операция переписывания, от которой рефлог чаще всего спасает.
- git stash — стеши имеют собственный рефлог под
stash@{n}. - git log — обычный просмотр истории;
git log -gчитает рефлог.