При работе с системой контроля версий Git вы можете в любой момент отменить внесенные изменения. В Git существует несколько способов, которые позволяют отменить последние внесенные изменения в необходимом коммите или ветки.
Одним из основных способов отмены (удаления) внесенных изменений в Git является команда git reset
. Команда git reset
предназначена для удаления коммита путем переноса указателя HEAD
назад к более старому (предыдущему) коммиту. Тем самым git reset
эмулирует ситуацию, как будто последнего коммита вообще не существовало.
Рассмотрим применение git reset
на конкретном примере. Предположим, мы только что сделали коммит, но поняли что забыли внести изменения или добавить нужный файл. Один из способов отмены внесенных изменений — сделать откат к предыдущему коммиту. Для этого воспользуемся следующей командой:
git reset HEAD~1
Где:
HEAD
— указатель на текущую ветку, а также указатель на последний коммит в этой ветке;~1
— количество коммитов, на которое необходимо произвести откат. В данном случае откат будет произведен на один коммит назад.Команда выше произведет откат на один коммит назад, при этом текущая рабочая директория и индекс Git останутся неизменными. На реальном примере это выглядит так:
test1.txt
со следующим содержимым:Hello, world!
Данный файл присутствует в git:
test1.txt
, удалив из него world!
, и применим данное изменение. В итоге у нас появится два коммита:Hello, world!
:git reset HEAD~1
git log
Обратите внимание, что второй коммит был удален. Также содержимое файла test1.txt
осталось нетронутым.
Несмотря на то, что команда git reset
кажется довольно простой в использовании, она поддерживает несколько различных режимов. Рассмотрим эти режимы более подробно.
Режим soft
предназначен для отмены последних коммитов. Изменения, которые были внесены в сами файлы, остаются в индексе. При использования режима soft
указатель HEAD
перемещается на выбранное количество коммитов назад. Изменения остаются в разделе проиндексированных файлов и в рабочем каталоге. Дерево объектов также не изменяется.
Рассмотрим работу режима soft
на практике. Предположим, мы сделали ошибочный коммит, и нам надо откатиться назад.
new-file.txt
и добавляем его в индекс:touch new-file.txt
git add new-file.txt
git commit -m "Add new-file.txt"
soft
:git reset --soft HEAD~1
git status
Как можно заметить, добавленный ранее файл new-file.txt
был возвращен в индекс, об этом в частности говорят строки:
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: new-file.txt
git commit -m "new correct commit"
Mixed
— режим, используемый по умолчанию. Предназначен для отмены последних внесенных изменений в коммите, а также сбрасывания индекса. При этом рабочая директория остается без изменений. Фактически команда git reset --mixed
аналогична команде git reset
.
Рассмотрим принцип работы режима mixed
на практике. Например, мы сделали коммит в который включили лишний файл. Нам необходимо сбросить индекс с дальнейшим добавлением только необходимых файлов. Воспроизведем данную ситуацию:
test1.txt
, test2.txt
, test3.txt
и после каждого добавленного файла делаем коммит:git add test1.txt
git commit -m "Added test1.txt file"
git add test2.txt
git commit -m "Added test2.txt file"
git add test3.txt
git commit -m "Added test3.txt file"
test3.txt
оказался лишним. Необходимо его убрать из индекса, но при этом не удалять. Для этого выполним команду:git reset --mixed HEAD~1
Аналогом команды выше является команда:
git reset HEAD~1
Она выполнит откат изменения на один коммит назад (в данном случае до коммита Added test2.txt file
).
git add test4.txt
git commit -m "Added test4.txt file"
Режим hard
предназначен для полного удаления всех изменений, которые были сделаны после коммита. Будут удалены любые изменения, внесенные в рабочую директорию и индекс. Отменить действия, выполненные при помощи git reset --hard, нельзя
, поэтому будьте осторожными при использовании данного режима. В качестве меры предосторожности рекомендуется сделать резервную копию файлов, к которым будет применяться режим hard
.
Рассмотрим принцип работы режима hard
на практике.
git add another_new_file.txt
git commit -m "Added another file"
another_new_file.txt
нам больше не нужен, мы можем полностью его удалить. Для этого воспользуемся командой:git reset --hard HEAD~1
Команда выше удалит ранее добавленный файл another_new_file.txt
, его коммит, а также его индекс.
Еще одним способом отмены внесенных изменений является команда git revert
. git revert
отличается от git reset
, несмотря на то, что обе эти команды выполняют одну и ту же функцию — отменяют изменения. В то время как git reset
изменяет историю репозитория при помощи перемещения указателя ветки (HEAD
) на необходимый коммит, git revert
создает новый коммит, а также не удаляет историю с ранее внесенными изменениями (коммитами). Тем самым вы полностью сохраняете структуру изменений вашего проекта.
Рассмотрим применение git revert
на практике. Предположим, у нас есть следующая история коммитов:
Нам необходимо сделать откат до третьего коммита с именем Edit test1.txt file
и хэш-суммой 536ac2cb42030f4de9ebf6fca977b6588487c016
. Для этого воспользуемся командой:
git revert HEAD~2
При выполнении команды выше откроется меню с вводом сообщения для нового коммита. Это эквивалентно вводу сообщения при помощи ключа -m
при использовании команды git commit
. Можно как ввести свое сообщение, так и оставить текст по умолчанию в формате "Revert <имя_коммита_к_которому_был_произведен_откат>"
.
После этого проверяем историю коммитов (git log
) и обнаруживаем новый коммит с пометкой revert
, в котором сказано, что данный коммит является revert-коммитом от коммита с именем Edit test1.txt
:
Тем самым мы не только сделали откат необходимого изменения, но и сохранили саму историю изменений.
Несмотря на то, что команда git checkout
предназначена для работы с ветками (в частности, для создания новых веток, а также для переключения между существующими ветками), ее можно использовать для отката изменений в одном определенном файле или в нескольких файлах сразу.
Предположим, мы внесли некоторые изменения в файл script.sh
и сделали коммит, однако вскоре поняли, что внесенные изменения нас не устраивают и нам необходимо вернуться к последнему коммиту для файла script.sh
. В таком случае необходимо выполнить команду:
git checkout HEAD -- script.sh
Команда выше вернет состояние файла script.sh
к последнему коммиту, который был сделан для файла script.sh
.
Если же необходимо вернуться не к последнему коммиту, а к другому, то необходимо знать хэш-сумму нужного коммита. Для этого сначала воспользуемся командой git log
, которая отобразит историю коммитов:
git log
Хэш-сумма отображается после слова commit
. В данном случае откатимся к коммиту с хэш-суммой e4dfe5bf3bab71add158ac1ca5dc3c59dc5ff38e
. Для этого выполняем команду:
git checkout e4dfe5bf3bab71add158ac1ca5dc3c59dc5ff38e -- script.sh
Git — многофункциональный инструмент, и в данной статье мы рассмотрели различные способы отмены изменений в системе контроля версий Git. Вы можете сравнить их особенности и выбрать тот способ, который подходит именно под ваши задачи.