Нет ничего более раздражающего для разработчика или инженера данных, чем случайное удаление веток 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.