Материал подготовлен командой Simple-Server для администраторов VPS и выделенных серверов. Команды и пути проверяйте на тестовой машине перед production.
Предварительные требования
Мы будем рассматривать практическую часть работы с git reset, поэтому нам необходимо заранее установить Git.
В качестве теста будем использовать операционную систему на ядре Linux, а именно выберем дистрибутив Ubuntu версии 22.04. Но можно использовать абсолютно любой дистрибутив Linux на ваш вкус, так как git присутствует практически во всех современных пакетных менеджерах.
В большинстве дистрибутивов git уже предустановлен заранее, однако установленная версия может незначительно отличаться от последней выпущенной. Также для дистрибутивов Ubuntu git можно установить, используя официальный репозиторий. Для этого необходимо выполнить следующие команды:
add-apt-repository ppa:git-core/ppa && apt -y install gitДля всех остальных Debian-based-дистрибутивов (Debian, Linux Mint, Kali Linux и т.д.) установку можно выполнить из стандартных репозиториев ОС при помощи команды:
Если же вы решите выбрать дистрибутивы, основанные на RHEL (RedHat, CentOS, Fedora, Oracle Linux), то команда установки будет варьироваться в зависимости от используемого пакетного менеджера:
# Пакетный менеджер yum:
yum -y install git
# Пакетный менеджер dnf:
dnf -y install gitПосле того как установка будет завершена, проверим корректность установки пакета при помощи вывода версии git:
Предназначение git reset — отмена внесенных локальных изменений. Если говорить техническим языком, то команда git reset сбрасывает указатель (ссылку) HEAD на предыдущий коммит в репозитории. Под HEAD понимается указатель на текущую ветку, который одновременно указывает еще и на последний коммит, сделанный в текущей ветке.
Команда git reset оперирует тремя механизмами (сущностями): рабочим каталогом, указателем HEAD и индексом. Все эти механизмы в терминологии git называются деревьями, т.к. их структура данных построена на основе узлов и указателей. Далее разберём данные механизмы более подробно.
Отдельно стоит отметить, что в различных веб-сервисах, использующих git, включая GitHub, GitLab и Bitbucket, присутствует возможность отмены действий при помощи веб-интерфейса. Однако, как правило, вместо git reset используется ее другой безопасный аналог — git revert, которая отличает от reset тем, что не удаляет коммиты из истории проекта, тем самым сохраняя всю историю вносимых изменений.
Под рабочим каталогом понимается та директория, где была выполнена команда git reset и хранятся файлы проекта, которые будут отправлены в репозиторий git. Для того чтобы система git понимала, какой каталог является рабочим, а какой нет, при выполнении команды git init в корне директории создается скрытая директория с именем .git, в которой хранятся конфигурационные файлы git.
Использование рабочего каталога выглядит следующим образом:
- Создаем новый каталог и переходим в него:
mkdir new_project && cd new_project-
Создаем новый репозиторий git:
-
После того как был инициирован новый репозиторий, в корне директории будет создана скрытая папка с именем git с конфигурационными файлами git:
Все дальнейшие операции по добавлению, удалению или изменению файлов будут происходить в рабочем каталоге git.
HEAD указывает на текущую ветку в репозитории, а ветка указывает на последний коммит в репозитории. Каждый раз при переключении на другую ветку (при помощи команды git checkout) указатель HEAD будет указывать на последний коммит в новой ветке.
На практике это выглядит следующим образом:
И добавляем его в репозиторий:
git commit -m "Initial commit"- Самый простой способ увидеть указатель
HEAD— выполнить командуgit cat-file:
Так как у нас один коммит, то указатель HEAD указывает на него.
- Теперь внесем изменения в ранее созданный файл
new1.txt:
echo "This is test file" > new1.txt
git commit -m "Added some info to new1.txt file"- Повторно выполняем команду:
Как можно увидеть на скриншоте выше, указатель HEAD указывает уже на другой последний коммит в ветке.
Индекс в git — это промежуточная область, в которую добавляются файлы с использованием git add. Индекс можно рассматривать как предварительный коммит — добавленные файлы уже присутствуют в репозитории и отслеживаются, но еще не добавлены в сам коммит. Стоит помнить, что когда файл находится в области индекса, он еще не является частью репозитория, и сам файл можно убрать из стадии индекса. Рассмотрим индекс на практике.
И добавляем его в индекс:
Файл находится в staging-этапе, он же индекс. Файл уже отслеживается git, но еще не добавлен в коммит.
В своей работе git reset может использовать три различных режима — Soft, Mixed, Hard.
Режим Soft используется для отмены последних внесенных изменений. С технической стороны при использовании режима soft происходит возврат указателя HEAD к указанному коммиту. При этом режим soft сохраняет все изменения, внесенные в индекс.
На практике режим soft работает следующим образом:
-
Создадим новый файл с именем
new3.txtв репозитории: -
Добавляем его в индекс (staging):
git commit -m “Added new3.txt file”Смотрим историю коммитов:
-
Теперь представим ситуацию, когда мы сделали коммит по ошибке и нам предстоит сделать откат:
-
Проверяем историю коммитов:
Как можно заметить на скриншоте выше, ранее присутствующий последний коммит, в котором был добавлен файл new3.txt, был удален, и указатель HEAD сместился на предыдущий коммит в репозитории.
Также режим soft возвращает добавленные файлы обратно в индекс:
Режим Mixed используется в команде git reset по умолчанию. Режим mixed производит отмену последнего внесенного изменения в коммите, а также сброс индекса. Сами файлы при этом не затрагиваются. На практике это выглядит следующим образом:
- Создаем три файла и добавляем их по одному:
git add new1.txt
git add new2.txt
git add new3.txt
git commit -m "Added three new files"Текущая история коммитов выглядит следующим образом:
-
В итоге мы получили ситуацию, когда все три файла были добавлены в рамках одного коммита. Теперь нам необходимо отменить последнее внесенное изменение, в данном случае — отменить добавление файла с именем
new3.txt: -
Проверяем историю коммитов после
git reset --mixed:
По итогу мы видим, что последний коммит был удален, а указатель HEAD вернулся на коммит назад. Также проверяем статус области индекса:
Файлы были возвращены в первоначальное состояние. Само содержимое файлов не затрагивается.
Третий и последний режим команды git reset называется Hard, и основным его предназначением, помимо удаления коммитов, является удаление файлов в репозитории. Выглядит это следующим образом: режим hard удаляет сам коммит, изменения в индексе и сами файлы. Данный режим колоссально отличается от двух других, так как по сути производит обновление рабочей директории до состояния индекса (до состояния, когда в репозитории были внесены какие-либо изменения).
-
Выведем список файлов в папке:
-
Добавляем файл
readme.mdв индекс:
git commit -m "Added readme.md file"- Теперь предположим, что добавленный файл не должен присутствовать в репозитории и его необходимо удалить. Также необходимо удалить коммит и состояние индекса. Воспользуемся режимом
hardкомандыgit reset:
Режим hard выводит в терминале часть кэша того коммита, к которому был совершен откат.
-
Смотрим историю изменений:
-
Проверяем статус индекса:
Статус индекса тоже был удален.
- Наконец проверяем файлы, которые остались в директории:
Ранее созданный файл с именем readme.md был успешно удален.
Режим hard необходимо использовать с повышенной осторожностью в связи с тем, что данный режим удаляет все внесенные изменения не только на уровне репозитория git (удаляет коммиты и статус индекса), но и на уровне файловой системы (удаляет файлы).
Откат на несколько коммитов назад
В начале статьи было упомянуто, что команда git reset позволяет сделать откат не только на коммит назад (конструкция HEAD~1), но и на любой другой, который присутствует в репозитории. Рассмотрим на конкретном практическом примере.
Предположим, что у нас присутствует репозиторий, в котором расположены четыре коммита:
Последний коммит в репозитории — это коммит с хэш-суммой bae2f49660c0807e46579fa2708040f329bc4717 и сообщением Added extra files. Например, следующая команда вернет состояние репозитория на коммит с хэш-суммой be401c3f5c55869ae04c333c9c19ef959634951a и сообщением Added new2.txt file:
Чтобы вернуться на два коммита назад, достаточно выполнить:
Проверяем текущий последний коммит:
Также произвести откат можно при помощи хэш-суммы коммита. Достаточно выбрать один из трех режимов (например, hard):
git reset --hard be401c3f5c55869ae04c333c9c19ef959634951aНужен сервер для практики? Закажите VPS на Simple-Server — root-доступ, NVMe, DDoS-защита и поддержка 24/7.