Git Reflog: Понимание и использование журналов ссылок в Git

Нет ничего более раздражающего для разработчика или инженера данных, чем случайное удаление веток git или сброс коммитов, когда вы этого не хотели. Вот почему я рад поделиться тем, что узнал из собственного опыта и о чем хотел бы узнать раньше, а именно, как использовать git reflog. git reflog — это одна из тех техник, которые определенно стоит изучить; если вы потратите немного времени сейчас, вы сможете избежать большой головной боли в будущем.

Хотя я покажу вам git reflog, который, на мой взгляд, действительно полезен для навигации и восстановления после ошибок, я также хочу порекомендовать наши курсы Основы Git и Введение в концепции GitHub, чтобы изучить все, что нужно знать о системах управления версиями.

Что такое git reflog?

Git reflog, или референсный журнал, — это локальный механизм отслеживания, который записывает обновления указателей веток и ссылки HEAD в репозитории Git. (В контексте Git HEAD относится к текущему коммиту, на основе которого строятся ваш рабочий каталог и область подготовки.)

В отличие от git log, который отображает историю коммитов на основе родословной, показывая, как коммиты связаны в ветке, git reflog фиксирует все перемещения HEAD, включая переключения веток, ребейсы, сбросы и коммиты. Это делает reflog полезным для восстановления потерянных коммитов и отладки недавних действий.

Когда создаются записи reflog?

Записи reflog создаются каждый раз, когда вы выполняете действия, изменяющие состояние HEAD или ссылок на ветки. Общие сценарии включают следующее:

  • Коммит изменений с помощью git commit.

  • Переключение на другую ветку с помощью git checkout branch_name.

  • Создание новой ветки с помощью git branch new_branch.

  • Перебазирование git rebase

  • Сброс к предыдущему коммиту git reset --hard.

  • Слияние веток с помощью git merge.

Вот код, который вы используете для отслеживания обновлений в локальном репозитории:

git reflog

Использование git reflog для отслеживания обновлений в локальном репозитории. Изображение автора.

Как вы интерпретируете вывод git reflog?

Вы можете интерпретировать вывод следующим образом:

  • HEAD@{0}: Самое последнее действие заключалось в переключении на ветку HEAD.

  • HEAD@{1}: До этого я изменил тип файла с .xlxs на формат .csv.

  • HEAD@{2}: Я сделал первый коммит при отправке файлов в репозиторий.

Каждая запись показывает:

  • Хэш коммита (fa82776)

  • Индекс reflog (HEAD@{0}, HEAD@{1} и т.д.)

  • Описание выполненного действия (коммит,checkout, rebase)

Как использовать git reflog

Команда Git reflog предоставляет способ отслеживать обновления ссылок и восстанавливать предыдущие состояния вашего репозитория. Понимая, как перемещаться по записям reflog, вы можете восстановить потерянные коммиты, отменить изменения и сравнивать предыдущие версии вашей работы.

Основная команда Git reflog

Ниже приведена основная команда reflog:

git reflog

Вышеуказанная команда отображает список недавних действий, которые обновили HEAD или ссылки на ветки, включая коммиты, переключения веток, сбросы, ребейзы и другое. Каждая запись проиндексирована, такая как HEAD@{0} и HEAD@{1}, чтобы представить свое положение в истории reflog.

Ссылки на предыдущие состояния

Git reflog служит записью прошлых обновлений ссылок, позволяя нам находить и восстанавливать предыдущие моменты в истории нашего репозитория. Без него эти ссылки не существовали бы, и нам потребовались бы точные хэш-коды коммитов, чтобы вернуться к конкретным прошлым состояниям. Теперь давайте рассмотрим, как Git позволяет нам перемещаться по этим прошлым состояниям, используя git checkout.

HEAD@{n}: Ссылается на конкретную запись reflog, где n — это индекс. Например, HEAD@{2} ссылается на третье по недавности состояние HEAD.

git checkout HEAD@{2}

Использование git checkout для отслеживания прошлых изменений. Изображение автора.

branch@{time}: Относится к состоянию ветки в определенное время. Например, main@{1.week.ago} относится к состоянию главной ветки неделю назад, в то время как feature@{yesterday} относится к состоянию ветки feature вчера.

git checkout main@{1.week.ago}

Использование git checkout для отслеживания прошлых изменений. Изображение автора.

Квалификаторы на основе времени

git reflog не только помогает нам восстановить прошлые состояния, но также позволяет сравнивать их. Поскольку reflog отслеживает обновления ссылок, мы можем использовать его, чтобы увидеть, как менялся наш репозиторий с течением времени. Теперь давайте посмотрим, как git diff использует записи reflog для сравнения прошлых и текущих состояний.

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

git checkout HEAD@{1.minute.ago} # Состояние от минуты назад
git checkout HEAD@{1.hour.ago} # Состояние от часа назад
git checkout HEAD@{1.week.ago} # Состояние от недели назад
git checkout HEAD@{yesterday} # Состояние на вчерашний день
git checkout HEAD@{2024-01-01.12:00:00} # Состояние на конкретный момент времени

Сравнение прошлых состояний с git diff

Вы можете сравнивать прошлые состояния, используя команды, такие как git diff. Следующая команда сравнивает текущее состояние основной ветки main@{0} с её состоянием за один день назад, main@{1.day.ago}. Вывод покажет любые различия между этими двумя снимками.

git diff main@{0} main@{1.day.ago}

Сравнение прошлых состояний с git diff. Изображение автора.

Общие сценарии использования Git Reflog

Git reflog – это бесценный инструмент для восстановления потерянных изменений, отмены ошибок и исправления распространённых проблем с Git. Ниже приведены некоторые практические сценарии, где git reflog может помочь.

Отмена плохого сброса

Если вы случайно сбросили свою ветку с помощью git reset --hard, вы можете использовать reflog для восстановления вашего предыдущего состояния.

git reset --hard HEAD@{3}

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

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

git reflog

Найдите хеш коммита из вывода reflog и проверьте его:

git checkout <commit-hash>

После того, как вы подтвердите потерянный коммит, вы можете создать новую ветку, чтобы сохранить его:

git branch recovered-branch <commit-hash>

Исправление испорченного ребейза

Если rebase пошел не так, вы можете использовать git reflog, чтобы найти коммит до rebase и сбросить вашу ветку. Найдите коммит перед rebase и сбросьте его.

git reset --hard HEAD@{3} # Настройте число в зависимости от вывода reflog

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

Если вы случайно удалили ветку, вы можете восстановить ее, используя git reflog. Найдите последний известный коммит удаленной ветки и воссоздайте ее:

git branch restored-branch <commit-hash>

Просмотр истории stash

Git reflog также можно использовать для просмотра истории stash. Команда ниже перечисляет операции со stash, позволяя вам восстановить более старые stash, если это необходимо.

git reflog stash

Для применения предыдущей записи в stash используйте следующую команду:

git stash apply stash@{2}

Ознакомьтесь с нашим учебным пособием Git Pull Force: Как перезаписать локальную ветку из удаленной, чтобы узнать лучшие практики по перезаписи локальных изменений.

Подкоманды и параметры Git Reflog

Git предоставляет несколько подкоманд и параметров для управления и взаимодействия с reflogs.

Подкоманды Git reflog

Ниже приведено структурированное описание основных подкоманд git reflog и их использование.

git reflog show: Отображает записи reflog для HEAD по умолчанию или для указанной ссылки, такой как ветка.

git reflog show

Используя git reflog show для отображения записей для указанной ссылки. Изображение от автора.

git reflog list: Эта команда отображает все ссылки с reflog. Это полезно для идентификации веток и ссылок HEAD с сохраненными записями reflog.

git reflog list

git reflog delete <ref>@{<specifier>}: Очищает старые записи reflog, которые превышают указанный временной лимит. Например, следующая команда удаляет записи старше 30 дней.

git reflog expire --expire=30.days.ago

git reflog delete <ref>@{<specifier>}: Удаляет определенную запись reflog на основе ее ссылки и позиции. Нижеприведенная команда удаляет запись reflog с индексом 2 для HEAD.

git reflog delete HEAD@{2}

git reflog exists <ref>: Проверяет, существует ли reflog для конкретной ссылки. Например, команда ниже вернет успех, если у основной ветки есть reflog.

git reflog exists main

Опции для подкоманд git reflog

Ниже приведены доступные опции для подкоманды git reflog и их использование.

--expire-unreachable=<time>: Удаляет только те записи reflog, которые недостижимы из любой ссылки. Например, команда ниже удаляет недостижимые записи reflog старше 7 дней.

git reflog expire --expire-unreachable=7.days.ago

--all: Обрабатывает reflog для всех ссылок, а не только для HEAD. Команда ниже очищает все reflog, старше 60 дней по всем веткам.

git reflog expire --expire=60.days.ago --all

--dry-run: Симулирует выполнение команды, показывая, что будет удалено, но на самом деле ничего не удаляет. Например, команда ниже отображает, какие записи будут удалены.

git reflog expire --expire=30.days.ago --dry-run

--verbose: Предоставляет подробный вывод о действиях, выполненных командой. Команда ниже показывает подробности в режиме verbose при истечении срока действия старых записей reflog.

git reflog expire --expire=90.days.ago --verbose

Git Reflog vs. Git Log: Основные различия

Как git log, так и git reflog предоставляют информацию о истории репозитория, но они служат разным целям. Давайте рассмотрим эти различия, чтобы понять, как каждый из них может быть использован для управления версиями и стратегий восстановления.

  • git log показывает историю коммитов, следуя за предками коммитов в ветке. Он предоставляет хронологический обзор того, как развивалось содержимое репозитория.

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

  • git reflog строго локален для вашей машины и не передается удаленным репозиториям.

  • В то время как git log не может восстановить коммиты, которые больше не являются частью родословной ветки, git reflog может помочь восстановить “потерянные” коммиты, отслеживая обновления ссылок, даже если эти коммиты больше недоступны из какой-либо ветки.

В таблице ниже обобщены эти ключевые различия.

Feature git log git reflog
Отслеживает коммиты Да Нет
Отслеживает обновления ссылок Нет Да
Доступно в удаленном Да Нет
Можно восстановить потерянные коммиты Нет Да

Лучшие практики использования Git Reflog

Git reflog — мощный инструмент для восстановления потерянных коммитов и исправления проблем в истории, но его эффективное использование требует осторожности. Вот несколько лучших практик, которые следует соблюдать при работе с reflog.

  • Используйте Reflog для восстановления и отладки: Если вы случайно сбросили или неправильно изменили ветку, проверьте git reflog, чтобы найти предыдущую ссылку и восстановить её.

  • Будьте осторожны с git reset --hard: git reset --hard может навсегда удалить несохраненные изменения. Всегда сначала проверяйте reflog, чтобы убедиться, что вы сможете восстановить данные, если что-то пойдет не так.

  • Храните резервные копии перед выполнением разрушительных команд: Чтобы защитить себя от потери данных, внедрите автоматизированные резервные копии ваших репозиториев Git. Всегда храните резервные копии в безопасном, удаленном месте, чтобы обеспечить возможность восстановления в случае сбоя оборудования или других катастроф.

  • Не полагайтесь только на reflog для долгосрочного восстановления:По умолчанию записи reflog хранятся в течение 90 дней. После этого периода они могут быть собраны мусорщиком и стать невосстанавливаемыми. Регулярно отправляйте ваши коммиты в удаленный репозиторий, чтобы гарантировать их сохранность за пределами вашего локального reflog.

  • Используйте git reflog expire для управления старыми записями: Если reflog вашего репозитория становится загроможденным, удалите старые или недоступные записи с помощью git reflog expire.

Заключение

Эффективное управление историей проекта в Git требует большего, чем простые команды. Изучение продвинутых инструментов, отслеживающих обновления ссылок, может обеспечить ценную защиту для восстановления потерянных коммитов, восстановления удаленных веток и исправления ошибок. Получение практического опыта работы с этими инструментами, а также командами, такими как git reset, git checkout и git revert, может значительно повысить вашу квалификацию в контроле версий.

Прохождение наших курсов – это не только отличный способ учиться, но и отличный способ сигнализировать работодателям, что вы серьезно относитесь к разработке программного обеспечения. В этой связи я рекомендую изучить наш пост в блоге Топ 20 вопросов и ответов на собеседовании по Git для всех уровней и пройти наш новый курс Основы Git, чтобы стать экспертом во всех аспектах Git.

Source:
https://www.datacamp.com/tutorial/git-reflog