↓Перейти к содержанию
  1. Git: руководства и команды/

git reflog: как спасти потерянные коммиты в Git

·5 минут·

Вы сделали git reset --hard, выполнили неудачный rebase или удалили ветку, и теперь коммиты «потеряны». Спокойно — Git хранит историю всех операций в специальном журнале reflog. Практически всё можно восстановить, если знать куда смотреть.

Что такое reflog #

git reflog — это журнал операций со ссылками (references log). Git записывает каждое изменение позиции HEAD: каждый коммит, checkout, merge, rebase, reset. Это локальная история, не синхронизируемая с сервером.

Reflog хранит записи по умолчанию 90 дней для коммитов и 30 дней для недоступных коммитов. Это ваша страховая сеть при любых «опасных» операциях.

Просмотр reflog #

# Базовый просмотр reflog
git reflog

# Пример вывода:
# a1b2c3d HEAD@{0}: reset: moving to HEAD~2
# b2c3d4e HEAD@{1}: commit: Добавить авторизацию
# c3d4e5f HEAD@{2}: commit: Исправить баг входа
# d4e5f6g HEAD@{3}: checkout: moving from main to feature
# e5f6g7h HEAD@{4}: merge feature: Fast-forward

Каждая строка содержит: хеш коммита, позицию в reflog (HEAD@{N}), тип операции и описание.

# Подробный просмотр с датами
git reflog --date=iso

# Последние 10 записей
git reflog -10

# Просмотр reflog конкретной ветки
git reflog show develop

# Просмотр в формате git log
git log -g --oneline

# Просмотр с относительным временем
git reflog --date=relative

Когда нужен reflog #

После git reset --hard: самый частый случай. Вы сбросили несколько коммитов и хотите вернуться.

После неудачного rebase: rebase завершился с ошибкой или результат не тот, что ожидался.

После удаления ветки: удалили ветку, а там были нужные коммиты.

После git checkout с потерей коммитов: переключились с «detached HEAD» и потеряли несохранённые коммиты.

Поиск потерянного коммита #

Задача: найти состояние репозитория ДО опасной операции.

# Просмотр reflog
git reflog

# Пример: ищем состояние до reset
# a1b2c3d HEAD@{0}: reset: moving to HEAD~3  ← текущее состояние
# b2c3d4e HEAD@{1}: commit: Важная функция    ← хотим сюда
# c3d4e5f HEAD@{2}: commit: Тест
# d4e5f6g HEAD@{3}: commit: Рефакторинг
# ...

# Посмотреть что было в нужном коммите
git show b2c3d4e

# Посмотреть разницу с текущим состоянием
git diff HEAD b2c3d4e

Если нужно найти коммит по сообщению:

# Поиск в reflog по сообщению коммита
git log -g --grep="важная функция"

# Поиск по части сообщения
git log -g --all --oneline | grep "функция"

Восстановление потерянного коммита #

Нашли нужный хеш — теперь восстановление.

Вариант 1: Полный сброс к потерянному состоянию

# Вернуть HEAD к нужному коммиту
git reset --hard b2c3d4e

# Если текущая работа нужна — сначала сохранить
git stash
git reset --hard b2c3d4e
git stash pop

Вариант 2: Создать ветку из потерянного коммита

# Безопаснее — создать новую ветку, не трогая текущую
git checkout -b recovery b2c3d4e
# или
git branch recovery b2c3d4e

Вариант 3: Cherry-pick нужных коммитов

# Применить конкретный коммит в текущую ветку
git cherry-pick b2c3d4e

Восстановление удалённой ветки #

# Посмотреть reflog в поиске последней позиции ветки
git reflog | grep "branch-name"
# или
git reflog --all | grep "branch-name"

# Пример вывода:
# a1b2c3d HEAD@{5}: checkout: moving from branch-name to main

# Восстановить ветку
git branch branch-name a1b2c3d

Восстановление после неудачного rebase #

# Перед rebase Git сохраняет позицию в ORIG_HEAD
git reset --hard ORIG_HEAD

# Если ORIG_HEAD не работает — через reflog
git reflog

# Найти строку вида:
# a1b2c3d HEAD@{N}: rebase -i (start): checkout master
# Взять хеш ДО этой строки — это состояние до rebase

git reset --hard <hash-before-rebase>

Практические примеры #

# Посмотреть всю историю операций
git reflog

# Найти состояние 2 часа назад
git reflog --since="2 hours ago"

# Посмотреть содержимое потерянного коммита
git show HEAD@{3}

# Восстановить к состоянию 5 шагов назад в reflog
git reset --hard HEAD@{5}

# Создать ветку из потерянного состояния
git branch recovery HEAD@{7}

# Применить изменения из потерянного коммита
git cherry-pick HEAD@{3}

# Найти коммит по сообщению
git log -g --grep="fix auth"

# Восстановить после reset --hard
git reflog
git reset --hard b2c3d4e

# Посмотреть reflog после rebase
git reflog --all | head -20

Reflog — это только локальная история #

Важное ограничение: reflog хранится только локально, в директории .git/logs/. Если вы клонировали репозиторий заново — reflog пустой. Если другой разработчик удалил коммиты на сервере — в вашем reflog они не появятся.

Это означает: восстановить потерянные коммиты через reflog можно только на той же машине, где они были созданы.

# Где хранится reflog
cat .git/logs/HEAD

# Reflog конкретной ветки
cat .git/logs/refs/heads/main

Часто задаваемые вопросы #

Как долго хранится reflog? По умолчанию 90 дней для достижимых коммитов и 30 дней для недостижимых. Можно изменить через git config gc.reflogExpire.

Могу ли я использовать reflog для восстановления на другом компьютере? Нет. Reflog хранится локально в .git/logs/. На другом компьютере или после нового clone — reflog будет пустым.

Что произойдёт, если очистить reflog? Потеряется история операций, и восстановление потерянных коммитов станет невозможным. Обычно очистку делать не нужно — это происходит автоматически по истечении срока.

Как найти конкретный коммит в reflog? Используйте git log -g --grep="сообщение" для поиска по тексту. Или просматривайте git reflog вручную с --date=relative для ориентации по времени.

Работает ли reflog после clone репо? Нет. После git clone reflog содержит только операции, выполненные в этом локальном репозитории. История операций на сервере недоступна.

Заключение #

git reflog — ваша страховка. Перед любой «опасной» операцией (git reset --hard, git rebase) запишите текущий хеш или просто знайте, что reflog есть. Почти любую ошибку можно исправить в течение 90 дней. Для понимания полного контекста операций используйте git log, а для отмены коммитов в опубликованных ветках — git revert.