Статьи

Git лаконично: отмена изменений

Весь смысл сохранения «безопасных» копий программного проекта — это спокойствие: если ваш проект внезапно сломается, вы будете знать, что у вас есть легкий доступ к функциональной версии, и вы сможете точно определить, где проблема был представлен. С этой целью запись фиксации бесполезна без возможности отмены изменений. Однако, поскольку Git имеет так много компонентов, «отмена» может иметь много разных значений. Например, вы можете:

  • Отменить изменения в рабочем каталоге
  • Отменить изменения в области подготовки
  • Отменить весь коммит

Чтобы усложнить ситуацию еще больше, есть несколько способов отменить коммит. Вы также можете:

  1. Просто удалите коммит из истории проекта.
  2. Оставьте коммит как есть, используя новый коммит, чтобы отменить изменения, внесенные первым коммитом.

У Git есть специальный инструмент для каждой из этих ситуаций. Начнем с рабочего каталога.


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

1
2
git reset —hard HEAD
git clean –f

Эта конфигурация git reset позволяет рабочему каталогу и рабочей области сопоставлять файлы в самом последнем коммите (также называемом HEAD ), эффективно уничтожая все незафиксированные изменения в отслеживаемых файлах. Чтобы избавиться от неотслеживаемых файлов, вы должны использовать команду git clean . Git очень осторожен при удалении кода, поэтому вы также должны указать опцию -f для принудительного удаления этих файлов.

Рисунок 12: Сброс всех незафиксированных изменений
Сброс всех незафиксированных изменений

Также возможно настроить таргетинг на отдельные файлы. Следующая команда приведет к тому, что один файл в рабочем каталоге будет соответствовать версии самого последнего коммита.

1
git checkout HEAD <file>

Эта команда вообще не меняет историю проекта, поэтому вы можете смело заменять HEAD на идентификатор фиксации, ветвь или тег, чтобы файл соответствовал версии в этом коммите. Но не пытайтесь сделать это с помощью git reset , так как это изменит вашу историю (объяснение в Undoing Commits ).

Рисунок 13: Возвращение файла с помощью git checkout
Возврат файла с помощью git checkout

В процессе настройки вашего следующего коммита вы иногда добавляете дополнительный файл на сцену. Следующий вызов git reset приведет к его отключению:

1
git reset HEAD <file>

--hard флага --hard указывает Git оставить рабочий каталог в одиночку (в отличие от git reset --hard HEAD , который сбрасывает каждый файл как в рабочем каталоге, так и на сцене). Этапная версия файла соответствует HEAD , а рабочий каталог сохраняет измененную версию. Как и следовало ожидать, это приводит к неизменным изменениям в вашем выводе git status .

Рисунок 14: Unstaging файла с git reset
Удаление файла с помощью git reset

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

Всегда универсальный git reset также можно использовать для перемещения задания HEAD .

1
git reset HEAD~1

Синтаксический параметр HEAD~1 указывает коммит, который происходит непосредственно перед HEAD (аналогично, HEAD~2 ссылается на второй коммит перед HEAD ). Перемещая ссылку HEAD назад, вы фактически удаляете самый последний коммит из истории проекта.

Рисунок 15: Перемещение HEAD в HEAD ~ 1 с git reset
Перемещение HEAD в HEAD~1 с git reset

Это простой способ удалить пару коммитов, которые были отклонены от темы, но он представляет серьезную проблему для совместной работы. Если бы другие разработчики начали создавать поверх коммита, который мы удалили, как бы они синхронизировались с нашим хранилищем? Они должны будут запросить у нас идентификатор коммита замены, вручную отследить его в вашем репозитории, перенести все свои изменения в этот коммит, разрешить конфликты слияния, а затем снова поделиться своими «новыми» изменениями со всеми. Только представьте, что произойдет в проекте с открытым исходным кодом с сотнями участников …

Дело в том, что не сбрасывайте публичные коммиты , но не стесняйтесь удалять приватные, которые вы никому не делили. Мы вернемся к этой концепции позже в этой сессии.

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

1
git revert <commit-id>

Это берет изменения в указанном коммите, выясняет, как отменить их, и создает новый коммит с результирующим набором изменений. Для Git и других пользователей возвратный коммит выглядит и действует как любой другой коммит — он просто отменяет изменения, внесенные ранее коммитом.

Рисунок 16: Отмена коммита с возвратом коммита
Отмена коммита с возвращенным коммитом

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

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

1
git commit —amend

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

Рисунок 17: Изменение самого последнего коммита
Внесение изменений в самый последний коммит

Этот урок представляет собой главу от Git Succinctly , бесплатной электронной книги от команды Syncfusion .