Git: Руководство по исправлению ошибок (Часть 1)
- Git: Руководство по исправлению ошибок (Часть 1)
- Git: Руководство по исправлению ошибок (Часть 2)
Работа с кодом — рискованное занятие: существует бесчисленное множество способов выстрелить себе в ногу! Но если вы используете Git в качестве системы контроля версий, у вас есть отличная подстраховка. Множество инструментов «отмены» помогут вам оправиться практически от любой катастрофы.
В первой статье мы рассмотрим различные ошибки и способы их исправления с помощью Git!
Отмена незафиксированных изменений в файле
Предположим, вы внесли изменения в файл и через некоторое время заметили, что ваши усилия ни к чему не приводят. Было бы лучше начать заново и отменить изменения в файле.
Хорошая новость заключается в том, что если вы ещё не зафиксировали изменения, отменить их довольно просто. Но есть и плохие новости: Вы не сможете вернуть назад изменения, после того, как отменили их! Поскольку они не были сохранены в «базе данных» Git, восстановить их невозможно!
Узнав это небольшое предупреждение, давайте отменим наши изменения в index.html
:
git restore index.html
Эта команда восстановит наш файл до последнего зафиксированного состояния, очистив его от любых локальных изменений.
Восстановления удалённых файлов
Давайте с предыдущим примером пойдём немного дальше. Допустим вы удалили index.html
, а не изменили его. Опять же, предположим, то вы ещё не внесли изменения в репозиторий.
Вам приятно будет узнать, что git restore
так же легко справится с этой ситуацией:
git restore index.html
Команде restore
всё равно что вы сделали с этим плохим файлом. Она просто воссоздаст своё последнее зафиксированное состояние.
Отмена некоторых изменений
Большинство дней — смесь хорошей и плохой работы. А иногда у нас бывает и то и другое в одном файле: Некоторые из ваших модификаций будут отличными (давайте проявим щедрость и назовём их гениальными), а другие подходят для мусорной корзины.
Git позволяет детально работать с изменениями. Использование git restore
с флагом -p
делает процедуру отмены более тонкой:
git restore -p index.html
Git берёт нас за руку и проводит по каждому фрагменту изменений в файле, спрашивая, хотим ли вы удалить его (в этом случае нужно нажать y) или оставить (нажав n):
Если вы используете приложение для работы с Git, вы можете пойти ещё дальше. Подобные приложения позволяют вам выбирать, какой код сохранить, удалить и обработать не только на уровне фрагментов, но и для отдельных строк. Один из таких инструментов Tower, над которым работает ваш покорный слуга.
Исправление последнего коммита/фиксации
Поднимите руку, если вы никогда не делал опечаток в сообщении коммита или не забывали добавить последнее изменение. Нет поднятых рук? Это то, о чём я думал. Поскольку опечатка в сообщении коммита распространённое явление, Git позволяет очень легко исправлять такие ошибки.
Опция --amend
позволяет изменить последний коммит (и только его):
git commit --amend -m "A message without typos"
Если вы забыли добавить определённое изменение, вы легко можете сделать это. Просто добавьте его как и любое другое изменение, с помощью команды git add
, а затем снова запустите git commit --amend
:
git add forgotten-change.txt
git commit --amend --no-edit
Опция --no-edit
сообщает Git, что вы не хотите изменять сообщение коммита.
Отмена последствий плохого коммита
В вышеперечисленных случаях мы быстро осознавали свои ошибки. Но часто мы узнаём об ошибке только спустя долгое время после её совершения. Плохой коммит сидит в истории изменений язвительно глядя на нас.
Конечно, есть решение и этой проблемы: команда git revert
! И это решает нашу проблему не разрушительным способом. Вместо того чтобы удалить наш плохой коммит из истории, он создаст новый, с противоположными изменениями.
Выполнить это в командной строке так же просто, как предоставить хэш исправления плохого коммита в git revert
.
git revert 2b504bee
Как уже упоминалось выше, это не удалит плохой коммит (что может быть проблематичным, если мы уже поделились им с коллегами в удалённом репозитории). Вместо этого будет автоматически создан новый коммит, содержащий отменённые изменения.
Восстановление предыдущего состояния проекта
Иногда приходится признать, что мы зашли в тупик. Возможно, пара последних коммитов не принесла никаких результатов, и лучше их отменить.
К счастью, решить эту проблему довольно просто. Просто нужно предоставить хэш SHA-1 ревизии, к которой хотим вернуться, команде git reset
. Любые коммиту сделанные после этой ревизии исчезнут из истории.
git reset --hard 2b504bee
Параметр --hard
гарантирует, что у нас останется чистая рабочая копия. В качестве альтернативы мы можем использовать параметр --mixed
для большей гибкости (и безопасности): --mixed
сохранит изменения, которые содержались в удалённых коммитах, как локальные изменения в нашей рабочей копии.
Восстановление утерянных коммитов с reflog
Вы уже заметили, что когда дело доходит до исправления ошибок, с Git возможно практически всё. Включая отмену отмены. Допустим, мы поняли, что git reset
, который мы выполняли выше, был не самой лучшей идеей.
Как вы догадались, эта проблема решается определённым инструментом. reflog
— своего рода журнал, где Git протоколирует перемещения указателя HEAD
. Другими словами, каждый раз, когда мы фиксируем изменения, проверяем, объединяем, перебазируем и т.д. В этом журнале создаётся новая запись. К счастью, это же происходит, когда мы используем git reset
!
Давайте откроем reflog
командой git reflog
. Взгляните, что у нас есть:
Первое, что нужно знать о reflog
— это то, что он упорядочен в хронологическом порядке. Поэтому неудивительно, что наша недавняя ошибка git reset
находится в самом верху. Если мы хотим отменить её, мы можем вернуть предыдущее состояние, которое также запротоколировано здесь, ниже!
Мы можем скопировать хэш коммита этого безопасного состояния и создать на его основе новую ветку:
git branch happy-ending e5b19e4
Конечно, мы могли использовать git reset e5b19e4
для возврата в предыдущее состояние. Однако я предпочитаю создавать новую ветку: она не имеет недостатков и позволяет проверить, действительно ли это то состояние, которое мне нужно.
Восстановление одного файла из предыдущего состояния
Пока мы работали только с целым проектом. Но, что ели мы хотим восстановить один файл, а не весь проект? Например, мы удалили файл, а позже выяснилось, что этого не нужно было делать. Нам придётся решить две проблемы:
- найти коммит в котором мы удалили файл
- потом (и только потом) восстановить его.
Поищем в истории коммитов наш утерянный файл:
git log -- <filename>
Результатом будет список всех коммитов, в которых этот файл изменялся. А поскольку журнал отсортирован в хронологическом порядке — коммит в котором мы удалили файл будет первым (так как после удаления файла, он не будет отображаться в новых коммитах).
В хэшем коммита и именем файла у нас есть всё необходимое для его восстановления.
git checkout <deletion commit hash>~1 -- <filename>
Обратите внимание, что мы используем ~1
для обращения к коммиту перед тем в котором мы его удалили. Это необходимо, поскольку коммит, в котором произошло удаление, больше не содержит файл. Поэтому мы не можем использовать его для восстановления файла.
Вы (почти) непобедимы
Читая эту статью мы стали свидетелями множества катастроф, но убедились, что в Git практически всё можно исправить! Узнав правильные команды, вы всегда сможете найти способ спасти положение.
Но чтобы стать действительно непобедимым (всего лишь в Git), вам необходимо дождаться второй части из этой серии. Мы рассмотрим ещё несколько сложных проблем, например, восстановление удалённой ветки, перемещение коммитов между ветками и как объединить несколько коммитов в один!
- Git: Руководство по исправлению ошибок (Часть 1)
- Git: Руководство по исправлению ошибок (Часть 2)