Что делает команда git reflog: полный практический гид
Введение
Иногда в Git всё идёт не по плану.
Удалили не ту ветку. Сделали git reset --hard не туда.
После rebase “пропали” коммиты.
Кажется, что проект сломался и всё пропало.
Чаще всего это не так.
В большинстве таких ситуаций помогает одна команда:
git reflog
Разберёмся, что она делает, как её читать и как с её помощью спасать “потерянные” коммиты и ветки.
Что такое git reflog простыми словами
Git хранит не только коммиты, но и историю того, куда указывал HEAD и ветки в прошлом.
Эта история и есть reflog (reference log — журнал ссылок).
Если по-простому:
git reflogпоказывает, как со временем перемещалисьHEADи ветки: какие коммиты были “последними” до всех ваших команд.
Ключевые моменты:
reflog— локальный.
Его видно только в вашем репозитории, он не передаётся поgit push.- В нём отражаются почти любые действия, которые двигают
HEADили ветки:commit,commit --amendmergerebaseresetcheckoutpull,fetch+merge/rebase
- По записям
reflogможно:- найти “потерянный” коммит;
- восстановить удалённую ветку;
- откатить неудачный
resetилиrebase.
Базовое использование git reflog
Самый простой вариант:
git reflog
Пример вывода (упрощённый):
4f3c9a1 HEAD@{0}: commit: Fix login bug
a1b2c3d HEAD@{1}: commit: Add login form
9e8d7c6 HEAD@{2}: reset: moving to HEAD~1
123abcd HEAD@{3}: checkout: moving from main to feature/login
...
Разберём одну строку:
4f3c9a1 HEAD@{0}: commit: Fix login bug
4f3c9a1— сокращённый хеш коммита.HEAD@{0}— текущая позицияHEAD(самое “свежее” состояние).commit— тип действия.Fix login bug— сообщение коммита или комментарий к действию.
Важно:
HEAD@{0}— это текущее состояние.HEAD@{1}— что было перед этим.HEAD@{2}— ещё раньше, и так далее.
Как работает синтаксис HEAD@{…} и веток
Git позволяет ссылаться на прошлые состояния с помощью специального синтаксиса.
HEAD@{N} — “как было N шагов назад”
Примеры:
git show HEAD@{1}
git show HEAD@{5}
Это покажет коммиты, на которые указывал HEAD 1 и 5 шагов назад.
Можно сделать reset на это состояние:
git reset --hard HEAD@{1}
Так можно отменить последний шаг, если он оказался неудачным.
HEAD@{<дата>} — “как было в момент времени”
Работают и такие варианты:
git show HEAD@{"yesterday"}
git show HEAD@{"2025-12-01 15:00:00"}
Git попытается найти состояние HEAD, актуальное на эту дату и время.
<ветка>@{N} — история конкретной ветки
Работает не только с HEAD, но и с ветками:
git reflog feature/login
Покажет reflog именно ветки feature/login.
Обращение к состоянию ветки:
git show feature/login@{2}
Это полезно, если в одной ветке происходило много rebase и reset.
Типичные сценарии использования git reflog
1. Откат неудачного git reset --hard
Один из самых частых случаев.
Сценарий:
- Сделали:
git reset --hard HEAD~3 - Поняли, что удалили нужные коммиты из текущей ветки.
- Паника.
Что делать:
- Смотрим reflog:
git reflogВ списке будет строка передreset, примерно так:a1b2c3d HEAD@{1}: reset: moving to HEAD~3 9e8d7c6 HEAD@{2}: commit: Add payment integrationНас интересует состояние до reset — как правило, этоHEAD@{1}илиHEAD@{2}, нужно посмотреть по контексту. - Откатываемся обратно:
git reset --hard HEAD@{1}
И всё: состояние ветки вернулось к тому виду, который был до неудачного reset.
2. Восстановление удалённой ветки
Сценарий:
git branch -D feature/login
Потом понимаем, что ветка ещё нужна.
Шаги:
- Смотрим reflog
HEADилиmain:git reflogНаходим строку, гдеcheckoutпереключался наfeature/login
или где видно нужный коммит по сообщению. Например:d4e5f6a HEAD@{7}: checkout: moving from main to feature/loginХешd4e5f6a— это нужный коммит. - Создаём ветку снова от этого коммита:
git checkout -b feature/login d4e5f6a
Ветка восстановлена.
3. Восстановление коммита после git commit --amend
Сценарий:
- Был коммит
A. - Сделали
git commit --amend→ получили новый коммитB. - Потом оказалось, что изменения из
Aвсё-таки нужны.
В reflog это выглядит примерно так:
1111111 HEAD@{1}: commit (amend): Fix login bug
2222222 HEAD@{2}: commit: Fix login bug
Где:
1111111— новый коммит (послеamend);2222222— старый коммит (доamend).
Можно:
git show HEAD@{2}
# или
git checkout 2222222
Если нужно вернуть именно этот коммит в текущую ветку:
git cherry-pick 2222222
4. Поиск потерянных коммитов после git rebase
После rebase история переписывается: появляются новые коммиты с новыми хешами, старые как будто “пропадают”.
На самом деле старые коммиты ещё какое-то время живут в объектной базе и доступны через reflog.
Шаги:
- Смотрим:
git reflog - Ищем строку, где упомянут
rebase:abcd123 HEAD@{3}: rebase finished: returning to refs/heads/feature/login efgh456 HEAD@{4}: rebase: checkout feature/login ijkl789 HEAD@{5}: commit: Old commit before rebase - Нужный старый коммит можно:
- посмотреть:
git show ijkl789 - вернуть в историю:
git cherry-pick ijkl789
- посмотреть:
5. Вернуться к состоянию “как было полчаса назад”
Можно использовать время в ссылках reflog.
Пример:
git show HEAD@{"30 minutes ago"}
Если состояние устраивает, можно:
git reset --hard HEAD@{"30 minutes ago"}
Или, если нужен другой момент:
git show HEAD@{"2025-12-09 14:30:00"}
Рабочий алгоритм: что делать, если “всё пропало”
Можно запомнить простой чек-лист.
- Не паниковать. Не делать новых коммитов и
gc.
Пока вы не сделали лишних действий, Git проще “отмотать”. - Посмотреть
reflog:git reflog - Найти строку до опасной команды (
reset,rebase,commit --amend,branch -D,checkout). - Определить нужное состояние:
- по хешу;
- по сообщению коммита;
- по описанию действия.
- Вернуться:
- через
git reset --hard <hash>— если хотите переписать ветку; - через
git checkout -b <branch> <hash>— если хотите создать новую ветку от того состояния; - через
git cherry-pick <hash>— если нужно вернуть только один коммит.
- через
Ограничения и настройки reflog
Reflog — не вечный
Записи в reflog:
- хранятся ограниченное время;
- со временем Git их удаляет.
По умолчанию (если настройки не менялись):
- достижимые объекты (на которые ведут ветки и теги) — около 90 дней;
- недостижимые — около 30 дней.
Эти значения можно настроить в .gitconfig:
[gc]
reflogExpire = 90 days
reflogExpireUnreachable = 30 days
Но важно помнить: reflog — не архив навсегда. Часто он выручает, но полагаться на него как на полноценный бэкап нельзя.
Reflog локален
Каждый локальный репозиторий имеет свой reflog:
- ваш;
- у коллеги;
- на CI-сервере;
- на удалённой машине.
Если вы удалили ветку на своей машине, на удалённом сервере её reflog может быть другим.
Через обычный git reflog удалённого репозитория не посмотреть.
Полезные команды рядом с git reflog
git show с reflog-ссылками
Посмотреть состояние в прошлый момент:
git show HEAD@{1}
git show main@{2}
git diff между состояниями
Посмотреть, что изменилось между двумя шагами:
git diff HEAD@{2} HEAD@{0}
Можно увидеть, что именно вы сделали за последние 2 шага.
git log -g — лог по reflog
Похож на обычный git log, но использует историю reflog:
git log -g
Можно сочетать с фильтрами:
git log -g --oneline --grep="login"
Так проще искать “потерянный” коммит по сообщению.
Заключение
git reflog — это “чёрный ящик” Git.
Он записывает, куда указывал HEAD и ветки после ваших действий.
Пока этот журнал жив:
- можно отменить неудачный
git reset --hard; - вернуть ветку после
git branch -D; - достать старый коммит после
commit --amendилиrebase; - откатиться к состоянию “как было час назад”.
Главное — помнить несколько вещей:
- почти всегда “потерянный” коммит можно найти в
reflog; git reflog— локальный инструмент, он не заменяет бэкапы и не живёт вечно;- чем меньше лишних действий после ошибки, тем проще всё восстановить.
Полезная привычка для разработчика:
как только кажется, что “всё пропало”, первым делом набрать:
git reflog
И очень часто оказывается, что всё ещё можно исправить одной-двумя командами.