Перейти к содержимому

git reflog

Определение

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

git reflog

Существует несколько команд git, которые принимают параметр ссылки (ref) для указания на конкретный коммит. Механизм reflog отслеживает историю обновлений этих ссылок в локальном репозитории.

Базовое использование команды git reflog

Обычно git reflog используется так:

git reflog

bash
git reflog

Это сокращение для следующего:

git reflog show HEAD

bash
git reflog show HEAD

Команда выше выводит reflog для HEAD. Вывод выглядит примерно так:

git reflog command

bash
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

bash
git reflog show --all

Передайте имя текущей ветки в git reflog show, если хотите увидеть reflog именно для неё. В примере ниже мы показываем reflog для ветки test_branch.

git reflog show branch

bash
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

bash
git reflog stash
#0d44de3 stash@{0}: WIP on git_reflog: a567574 adding Vue.js

Reflog с указанием времени

Каждая запись 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

bash
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

bash
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

bash
git reflog expire --expire=1.day.ago

Delete - подкоманда git reflog delete

Подкоманда git reflog delete предназначена для удаления конкретных записей reflog. Обычные пользователи, как правило, избегают этой команды из-за риска потери данных, аналогично git reflog expire. Чтобы удалить конкретную запись, можно передать её ссылку:

git reflog delete example

bash
git reflog delete HEAD@{1}

Восстановление потерянных коммитов

Коммиты в Git никогда не теряются по-настоящему, даже во время операций переписывания истории. Рассмотрим пример git log --pretty=oneline, который выглядит так:

Recovering lost commits

bash
2b43ceab309da94256db8fb1f35b1678fb74abd4 changes in content
c32557493a95185997c87e0bc3a9481715279351 adding Vue.js
abc234f986d270d7f97c77618314a06f024c4563 migrating content
a5673cd762d8ef2e146d7f0226e81a92f91956b1 adding git reflog outline
2bce4a4404c42128bee8468a9517418ed0ea412 initial commit

Теперь предположим, что мы зафиксировали в этом репозитории несколько новых изменений и выполнили следующее:

the git reflog command

bash
#make changes to HEAD
git commit -am "API changes"

В результате журнал теперь выглядит так:

git reflog definition

bash
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

bash
git rebase -i origin/master

Во время rebase подкоманда s помечает коммиты для объединения в самый последний коммит "API changes". В результате объединения коммитов вывод git log теперь выглядит так:

git reflog usage

bash
40d8a1237656e19d4e4f1a9b419f57850c8f1974 API changes
35aee4a4404c42128bee8468a9517418ed0eb3dc initial commit

Теперь кажется, что объединённые коммиты исчезли. Если вам нужно работать с таким объединённым коммитом, можно воспользоваться reflog.

git reflog description

bash
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

bash
git reset HEAD@{2}

Эта команда переместит HEAD на тот коммит с "API changes" и восстановит остальные объединённые коммиты.

Практика

Какие утверждения о команде `git reflog` верны согласно руководству W3Docs по Git?

Считаете ли это полезным?

Предпросмотр dual-run — сравните с маршрутами Symfony на продакшене.