git reflog
Определение
Команда git reflog записывает обновления, сделанные в локальных ссылках, таких как ветки, HEAD и stash. Она позволяет возвращаться к коммитам, включая те, на которые не ссылается ни одна ветка или тег. После переписывания истории reflog содержит сведения о предыдущем состоянии ссылок и при необходимости позволяет вернуться к этому состоянию.

Существует несколько команд git, которые принимают параметр ссылки (ref) для указания на конкретный коммит. Механизм reflog отслеживает историю обновлений этих ссылок в локальном репозитории.
Базовое использование команды git reflog
Обычно git reflog используется так:
git reflog
git reflogЭто сокращение для следующего:
git reflog show HEAD
git reflog show HEADКоманда выше выводит reflog для HEAD. Вывод выглядит примерно так:
git reflog command
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Ссылки reflog
По умолчанию git reflog выводит reflog для ссылки HEAD, которая указывает на текущую активную ветку. К ссылке git можно обратиться с помощью синтаксиса name@{qualifier}.
Выполните следующую команду, чтобы получить полный reflog всех ссылок:
git reflog show --all
git reflog show --allПередайте имя текущей ветки в git reflog show, если хотите увидеть reflog именно для неё. В примере ниже мы показываем reflog для ветки test_branch.
git reflog show branch
git reflog show test_branch
#32a591f test_branch@{0}: commit: add snippets
#23bae4a test_branch@{1}: commit (initial): initial commitИспользование команды ниже выведет reflog для git stash::
git reflog stash
git reflog stash
#0d44de3 stash@{0}: WIP on git_reflog: a567574 adding Vue.jsReflog с указанием времени
Каждая запись reflog имеет связанный временной штамп. Их можно использовать как квалификаторы в синтаксисе указателя на ссылку Git, что позволяет фильтровать reflog 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, например так:
timed reflogs
git diff master@{0} master@{1.week.ago}Эта команда показывает diff текущей ветки master по сравнению с master недельной давности.
Подкоманды git reflog
Git reflog принимает несколько аргументов, которые работают как подкоманды. Они описаны ниже.
Show - подкоманда git reflog show
Подкоманда git reflog show — это псевдоним для git log -g --abbrev-commit --pretty=oneline. Это поведение по умолчанию. В следующем примере две команды эквивалентны:
git reflog show equivalence
git reflog master@{0}
git reflog show master@{0}Expire - подкоманда git reflog expire
Подкоманда git reflog expire используется для очистки старых или недостижимых записей reflog. Из-за риска потери данных эту подкоманду обычно не используют напрямую; Git применяет её внутренне. По умолчанию записи reflog истекают через 90 дней. Можно указать собственное время истечения с помощью аргумента --expire:
git reflog expire example
git reflog expire --expire=1.day.agoDelete - подкоманда git reflog delete
Подкоманда git reflog delete предназначена для удаления конкретных записей reflog. Обычные пользователи, как правило, избегают этой команды из-за риска потери данных, аналогично git reflog expire. Чтобы удалить конкретную запись, можно передать её ссылку:
git reflog delete example
git reflog delete HEAD@{1}Восстановление потерянных коммитов
Коммиты в Git никогда не теряются по-настоящему, даже во время операций переписывания истории. Рассмотрим пример git log --pretty=oneline, который выглядит так:
Recovering lost commits
2b43ceab309da94256db8fb1f35b1678fb74abd4 changes in content
c32557493a95185997c87e0bc3a9481715279351 adding Vue.js
abc234f986d270d7f97c77618314a06f024c4563 migrating content
a5673cd762d8ef2e146d7f0226e81a92f91956b1 adding git reflog outline
2bce4a4404c42128bee8468a9517418ed0ea412 initial commitТеперь предположим, что мы зафиксировали в этом репозитории несколько новых изменений и выполнили следующее:
the git reflog command
#make changes to HEAD
git commit -am "API changes"В результате журнал теперь выглядит так:
git reflog definition
37656e19d4e4f1a9b419f57850c8f1974f871b07 API changes
2b43ceab309da94256db8fb1f35b1678fb74abd4 changes in content
c32557493a95185997c87e0bc3a9481715279351 adding Vue.js
abc234f986d270d7f97c77618314a06f024c4563 migrating content
a5673cd762d8ef2e146d7f0226e81a92f91956b1 adding git reflog outline
2bce4a4404c42128bee8468a9517418ed0ea412 initial commitНа этом этапе, чтобы выполнить интерактивный rebase относительно ветки master, нужно выполнить следующее:
git reflog example
git rebase -i origin/masterВо время rebase подкоманда s помечает коммиты для объединения в самый последний коммит "API changes". В результате объединения коммитов вывод git log теперь выглядит так:
git reflog usage
40d8a1237656e19d4e4f1a9b419f57850c8f1974 API changes
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commitТеперь кажется, что объединённые коммиты исчезли. Если вам нужно работать с таким объединённым коммитом, можно воспользоваться reflog.
git reflog description
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 changesВ reflog есть записи о начале и завершении rebase, а перед ними — коммит "API changes". Ссылку из reflog можно передать в git reset, чтобы выполнить сброс к коммиту до rebase.
git reset HEAD
git reset HEAD@{2}Эта команда переместит HEAD на тот коммит с "API changes" и восстановит остальные объединённые коммиты.
Практика
Какие утверждения о команде `git reflog` верны согласно руководству W3Docs по Git?