# git reflog _Инструменты · GitLab Knowledge Base_ **TL;DR:** Журнал всех движений HEAD на этой машине. По умолчанию записи про достижимые коммиты живут 90 дней, про недостижимые - 30. Главный инструмент восстановления после `reset --hard`, `--amend`, `rebase` и удаления ветки. Хранится локально в `.git/logs/`. Reflog отвечает на вопрос «где была HEAD пять минут назад» и потому позволяет восстановить почти любое состояние, в котором ты успел побывать недавно. ## Базовая форма ```bash git reflog # a1b2c3d HEAD@{0}: reset: moving to HEAD~3 # 4d5e6f7 HEAD@{1}: commit: feat: add login # 8a9b0c1 HEAD@{2}: commit: docs: update README # ... ``` Каждая строка - состояние HEAD на момент действия. Чем выше - тем свежее. Колонки: SHA → синтаксический указатель → причина. ## Самый частый сценарий После катастрофического reset: ```bash git reset --hard HEAD~10 # ой, не туда git reflog # первая строка показывает SHA после reset, # вторая - SHA до reset git reset --hard HEAD@{1} # вернуться в состояние до reset ``` Или явно по SHA: ```bash git reset --hard 4d5e6f7 # из reflog ``` ## Что покрывает Reflog запоминает практически все операции, двигающие HEAD: - `commit`, `commit --amend` - `checkout`/`switch` между ветками - `merge`, `rebase` (целая серия записей) - `reset --hard`, `reset --soft` - `pull` (через свой merge/rebase двигает HEAD; чистый `fetch` HEAD не трогает - он обновляет только `refs/remotes/*`, и у тех есть свой отдельный reflog) - Создание/удаление веток через `branch -d/-D` (последняя позиция той ветки) Также есть отдельный reflog у каждой ветки: ```bash git reflog show feature # история позиций ветки feature git reflog show HEAD # == git reflog ``` ## Когда reflog НЕ поможет - **Незакоммиченные правки.** Если файл был только в working tree или индексе, никогда не закоммичен - reflog его не видит. Reflog ловит только коммиты. - **Untracked-файлы, удалённые `git clean -fd`.** Тот же случай. - **Чужие машины.** Reflog локальный. У коллеги свой reflog, твоих действий в нём нет. - **Старше срока reflog'а.** По умолчанию 90 дней для достижимых объектов, 30 для недостижимых. После - `git gc` подметает. - **После явного `git gc --prune=now` + `git reflog expire`.** Эти команды стирают историю принудительно. ## Поправки сроков Если работаешь с очень долгоживущими ветками или хочешь подольше страховку: ```bash git config --global gc.reflogExpire "180 days" git config --global gc.reflogExpireUnreachable "90 days" ``` Или наоборот - выключить reflog (редко нужно, занимает место): ```bash git config --global gc.reflogExpire 0 git config --global gc.reflogExpireUnreachable 0 ``` ## Подводные камни - **HEAD@{N} ≠ HEAD~N.** Первое - N-е состояние в reflog (по времени). Второе - N-й предок коммита (по графу). Это разные вещи. - **`HEAD@{yesterday}`, `HEAD@{2.hours.ago}`** - синтаксис «по времени». Удобно: `git diff HEAD@{1.week.ago} HEAD`. - **Reflog хранится в `.git/logs/`** - просто текстовые файлы. Можно посмотреть руками, но обычно `git reflog` удобнее. - **На свежеклоненном репозитории reflog пуст.** История хранится не в reflog, а в коммитах. Reflog - только про *локальные* движения HEAD, которых на новом clone ещё нет. ## Команды ```bash git reflog ``` Журнал движений HEAD (по умолчанию 90 дней для reachable, 30 для unreachable) ```bash git reset --hard HEAD@{1} ``` Откатиться к предыдущему состоянию HEAD ```bash git reflog show ``` История позиций конкретной ветки ```bash git diff HEAD@{1.week.ago} HEAD ``` Что поменялось у меня локально за неделю ## См. также - [git stash](/courses/git/kb/stash.md) - [git commit --amend](/courses/git/kb/amend.md)