Как безопасно отменить ошибки Git: Объяснение команд Revert, Reset и Checkout
Уверенно управляйте ошибками Git! Это руководство объясняет, как использовать `git revert`, `git reset` и `git checkout` для безопасной отмены коммитов, восстановления файлов и управления историей вашего репозитория. Узнайте, когда и как использовать каждую команду для исправления ошибок без потери ценной работы, что делает это чтение обязательным для любого пользователя Git.
Как безопасно исправлять ошибки в Git: объяснение Revert, Reset и Checkout
Ошибки в Git обычно кажутся хуже, чем они есть на самом деле. Вы могли закоммитить не тот файл, проиндексировать слишком много или запушить неудачное изменение в общую ветку. Безопасное исправление зависит от одного вопроса: было ли изменение уже опубликовано?
Это руководство объясняет, когда использовать git revert, git reset и git checkout, с примерами, которые можно аккуратно копировать. Краткая версия проста: используйте git revert для общих коммитов, git reset для локальной очистки и git checkout только когда вы намерены переключить ветку или восстановить более старые состояния файлов.
Сначала проверьте, что вы собираетесь отменить
Перед выполнением любой команды отмены посмотрите на текущее состояние:
git status
git log --oneline --decorate -5
git status показывает, есть ли у вас неиндексированные, индексированные или неотслеживаемые изменения. git log показывает последние коммиты и на что указывает ваша ветка.
Если у вас есть локальная работа, которую вы не хотите потерять, сначала создайте резервную ветку:
git branch backup-before-undo
Эта ветка даст вам простой путь назад, если вы выберете неправильную команду.
Используйте git revert для уже запушенных коммитов
git revert создает новый коммит, который применяет противоположность более раннему коммиту. Он не удаляет историю, поэтому это самый безопасный выбор для общих веток, таких как main, develop или любой другой ветки, которую могли склонировать другие.
Предположим, ваша история выглядит так:
A -- B -- C -- D main
Коммит C внес ошибку, но D хорош и должен остаться. Найдите хеш коммита:
git log --oneline
Затем отмените только этот коммит:
git revert abcdef1
Git открывает редактор для сообщения коммита отмены. После сохранения история выглядит так:
A -- B -- C -- D -- E main
Коммит E отменяет изменения из C. Все могут нормально запушить этот новый коммит.
Отмена мерж-коммита
Мерж-коммиты требуют один дополнительный флаг, потому что Git должен знать, какой родитель является основной линией:
git revert -m 1 <хеш-мерж-коммита>
Для обычного слияния в main флаг -m 1 обычно означает "сохранить первого родителя", то есть ветку, в которую вы сливали. Не гадайте здесь. Сначала выполните это и проверьте родителей:
git show --summary <хеш-мерж-коммита>
Если вы не уверены, какого родителя оставить, спросите коллегу или протестируйте отмену на временной ветке.
Используйте git reset для локальных коммитов
git reset перемещает указатель текущей ветки. В зависимости от режима, он также может изменить область индексации и ваши рабочие файлы. Используйте его в основном для коммитов, которые вы не запушили.
Снять файл с индексации
Если вы проиндексировали не тот файл, снимите его с индексации без изменения содержимого файла:
git restore --staged unwanted_file.txt
В старых примерах Git часто используется эквивалентная команда:
git reset HEAD unwanted_file.txt
Обе команды удаляют файл из области индексации. Ваши правки остаются в рабочей директории.
Отменить последний коммит, но оставить изменения проиндексированными
Используйте --soft, когда сообщение коммита было неверным или вы хотите добавить еще один файл перед повторным коммитом:
git reset --soft HEAD~1
Ваша ветка откатывается на один коммит, но изменения из этого коммита остаются проиндексированными.
Отменить последний коммит и оставить изменения неиндексированными
Используйте смешанный сброс по умолчанию, когда вы хотите переработать файлы перед повторным коммитом:
git reset HEAD~1
Это перемещает ветку назад на один коммит и оставляет изменения в вашей рабочей директории.
Отбросить локальные коммиты и изменения файлов
--hard сбрасывает ветку, область индексации и отслеживаемые файлы в вашей рабочей директории:
git reset --hard HEAD~1
Используйте это только когда вы уверены, что вам не нужны отброшенные изменения. Он не удаляет неотслеживаемые файлы, но отбрасывает правки отслеживаемых файлов без повторного запроса.
Используйте git checkout осторожно
git checkout имеет две распространенные задачи в старых рабочих процессах Git: переключение веток и восстановление файлов. Новые версии Git разделили эти задачи на более понятные команды: git switch для веток и git restore для файлов.
Чтобы переключить ветку:
git switch main
Старый эквивалент:
git checkout main
Чтобы отбросить незакоммиченные изменения в одном отслеживаемом файле:
git restore my_file.txt
Старый эквивалент:
git checkout -- my_file.txt
Это восстановление файла разрушительно для незакоммиченных правок в выбранном файле. Если вам могут понадобиться правки позже, сначала спрячьте их:
git stash push -m "сохранить работу перед восстановлением"
Используйте git reflog, если вы зашли слишком далеко
Если вы выполнили git reset --hard или случайно переместили ветку, git reflog может все еще показать, куда указывал HEAD:
git reflog
Вы можете увидеть более раннюю запись, например HEAD@{2} или хеш коммита до сброса. Вы можете создать ветку восстановления из нее:
git branch recovery <хеш-коммита>
Reflog является локальным для вашего клона и не является системой резервного копирования, но часто спасает от недавних ошибок.
Какую команду выбрать?
Используйте git revert, когда плохой коммит уже запушен или другие люди могли основывать на нем свою работу.
Используйте git reset --soft, когда ваш последний локальный коммит нужно переделать, но изменения все еще верны.
Используйте git reset, когда вы хотите вернуть последний локальный коммит как неиндексированные изменения файлов.
Используйте git reset --hard только когда локальные отслеживаемые изменения можно удалить.
Используйте git restore или git checkout -- <файл>, когда вы хотите отбросить незакоммиченные изменения в конкретных файлах.
Самая безопасная привычка — проверять git status, создавать временную резервную ветку, когда ставки высоки, и избегать перезаписи общей истории. Если коммит попал в общий удаленный репозиторий, git revert обычно является самым чистым исправлением.