Бесплатная миграция IT-инфраструктуры в облако

Команда git reset

Александр Бархатов
Александр Бархатов
Технический писатель
21 августа 2024 г.
143
9 минут чтения
Средний рейтинг статьи: 5

Сегодня трудно представить работу программиста или другого IT-специалиста без контроля версий. Среди инструментов SCM особое внимание заслуживает Git, который быстро завоевал всеобщую популярность и негласно считается стандартом в мире систем контроля версий. Git позволяет легко отслеживать изменения в файлах проекта, работать с функционалом веток, организовывать совместную разработку, хранить код и другие файлы централизованно. Также одной из сильных сторон Git является возможность гибкой отмены и удаления внесенных изменений. Одним из вариантов отмены изменений является команда git reset, поддерживающая три режима работы. В рамках данной статьи мы рассмотрим, как можно отменить внесенные изменения при помощи команды git reset, а также ее режимы работы на практических примерах.

Предварительные требования

Мы будем рассматривать практическую часть работы с 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 и т.д.) установку можно выполнить из стандартных репозиториев ОС при помощи команды:

apt -y install git

Если же вы решите выбрать дистрибутивы, основанные на RHEL (RedHat, CentOS, Fedora, Oracle Linux), то команда установки будет варьироваться в зависимости от используемого пакетного менеджера:

# Пакетный менеджер yum:
yum -y install git

# Пакетный менеджер dnf:
dnf -y install git

После того как установка будет завершена, проверим корректность установки пакета при помощи вывода версии git:

git --version

Описание git reset

Предназначение 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.

Использование рабочего каталога выглядит следующим образом:

1) Создаем новый каталог и переходим в него:

mkdir new_project && cd new_project

2) Создаем новый репозиторий git:

git init

Image14

3) После того как был инициирован новый репозиторий, в корне директории будет создана скрытая папка с именем git с  конфигурационными файлами git:

Image9

Все дальнейшие операции по добавлению, удалению или изменению файлов будут происходить в рабочем каталоге git.

Указатель HEAD

HEAD указывает на текущую ветку в репозитории, а ветка указывает на последний коммит в репозитории. Каждый раз при переключении на другую ветку (при помощи команды git checkout) указатель HEAD будет указывать на последний коммит в новой ветке.

На практике это выглядит следующим образом:

1) Создаем новый файл:

touch new1.txt

И добавляем его в репозиторий:

git add new1.txt

2) Делаем коммит:

git commit -m "Initial commit"

Image8

3) Самый простой способ увидеть указатель HEAD — выполнить команду git cat-file:

git cat-file -p HEAD

Image15

Так как у нас один коммит, то указатель HEAD указывает на него. 

4) Теперь внесем изменения в ранее созданный файл new1.txt:

echo "This is test file" > new1.txt

Добавляем файл в git:

git add new1.txt

5) Делаем коммит:

git commit -m "Added some info to new1.txt file"

Image19

6) Повторно выполняем команду:

git cat-file -p HEAD

Image16

Как можно увидеть на скриншоте выше, указатель HEAD указывает уже на другой последний коммит в ветке.

Индекс

Индекс в git — это промежуточная область, в которую добавляются файлы с использованием git add. Индекс можно рассматривать как предварительный коммит — добавленные файлы уже присутствуют в репозитории и отслеживаются, но еще не добавлены в сам коммит. Стоит помнить, что когда файл находится в области индекса, он еще не является частью репозитория, и сам файл можно убрать из стадии индекса. Рассмотрим индекс на практике.

1) Создаем файл:

touch new2.txt

И добавляем его в индекс:

git add new2.txt

2) Проверяем статус:

git status

Image4

Файл находится в staging-этапе, он же индекс. Файл уже отслеживается git, но еще не добавлен в коммит.

vds

Режимы git reset

В своей работе git reset может использовать три различных режима — Soft, Mixed, Hard.

Режим Soft

Режим Soft используется для отмены последних внесенных изменений. С технической стороны при использовании режима soft происходит возврат указателя HEAD к указанному коммиту. При этом режим soft сохраняет все изменения, внесенные в индекс. 

На практике режим soft работает следующим образом:

1) Создадим новый файл с именем new3.txt в репозитории:

touch new3.txt

2) Добавляем его в индекс (staging):

git add new3.txt

3) Создаем коммит:

git commit -m “Added new3.txt file”

Смотрим историю коммитов:

git log

Image18

4) Теперь представим ситуацию, когда мы сделали коммит по ошибке и нам предстоит сделать откат:

git reset --soft HEAD~1

5) Проверяем историю коммитов:

git log

Image13

Как можно заметить на скриншоте выше, ранее присутствующий последний коммит, в котором был добавлен файл new3.txt, был удален, и указатель HEAD сместился на предыдущий коммит в репозитории.

Также режим soft возвращает добавленные файлы обратно в индекс:

git status

Image7

Режим Mixed

Режим Mixed используется в команде git reset по умолчанию. Режим mixed производит отмену последнего внесенного изменения в коммите, а также сброс индекса. Сами файлы при этом не затрагиваются. На практике это выглядит следующим образом:

1) Создаем три файла и добавляем их по одному:

touch new{1..3}.txt
git add new1.txt
git add new2.txt
git add new3.txt

2) Далее создаем коммит:

git commit -m "Added three new files"

Текущая история коммитов выглядит следующим образом:

Image21

3) В итоге мы получили ситуацию, когда все три файла были добавлены в рамках одного коммита. Теперь нам необходимо отменить последнее внесенное изменение, в данном случае — отменить добавление файла с именем new3.txt:

git reset HEAD~1

4) Проверяем историю коммитов после git reset --mixed:

Image3

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

git status

Image5

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

Режим Hard

Третий и последний режим команды git reset называется Hard, и основным его предназначением, помимо удаления коммитов, является удаление файлов в репозитории. Выглядит это следующим образом: режим hard удаляет сам коммит, изменения в индексе и сами файлы. Данный режим колоссально отличается от двух других, так как по сути производит обновление рабочей директории до состояния индекса (до состояния, когда в репозитории были внесены какие-либо изменения).

1) Выведем список файлов в папке:

ls -l

Image11

Создаем новый файл:

touch readme.md

2) Добавляем файл readme.md в индекс:

git add readme.md

Смотрим статус:

git status

Image1

3) Делаем новый коммит:

git commit -m "Added readme.md file"

Image6

4) Теперь предположим, что добавленный файл не должен присутствовать в репозитории и его необходимо удалить. Также необходимо удалить коммит и состояние индекса. Воспользуемся режимом hard команды git reset:

git reset --hard HEAD~1

Image10

Режим hard выводит в терминале часть кэша того коммита, к которому был совершен откат.

5) Смотрим историю изменений:

git log

Image22

6) Проверяем статус индекса:

git status

Image12

Статус индекса тоже был удален.

7) Наконец проверяем файлы, которые остались в директории:

ls -l

Image20

Ранее созданный файл с именем readme.md был успешно удален.

Режим hard необходимо использовать с повышенной осторожностью в связи с тем, что данный режим удаляет все внесенные изменения не только на уровне репозитория git (удаляет коммиты и статус индекса), но и на уровне файловой системы (удаляет файлы).

Откат на несколько коммитов назад 

В начале статьи было упомянуто, что команда git reset позволяет сделать откат не только на коммит назад (конструкция HEAD~1), но и на любой другой, который присутствует в репозитории. Рассмотрим на конкретном практическом примере. 

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

git log

Image2

Последний коммит в репозитории — это коммит с хэш-суммой bae2f49660c0807e46579fa2708040f329bc4717 и сообщением Added extra files. Например, следующая команда вернет состояние репозитория на коммит с хэш-суммой be401c3f5c55869ae04c333c9c19ef959634951a и сообщением Added new2.txt file:

git reset HEAD~1

Чтобы вернуться на два коммита назад, достаточно выполнить:

git reset HEAD~2

Проверяем текущий последний коммит:

git log

Image17

Также произвести откат можно при помощи хэш-суммы коммита. Достаточно выбрать один из трех режимов (например, hard): 

git reset --hard be401c3f5c55869ae04c333c9c19ef959634951a
Выгодные тарифы на VDS/VPS в Timeweb Cloud

Заключение

В статье мы подробно ознакомились с git reset и ее режимами: soft, mixed, hard. Команда git reset является мощным инструментом, обладающим богатым функционалом и позволяющим отменять внесенным изменения. Однако, для ее эффективного использования необходимо четко представлять, как работает каждый режим, и особенно аккуратно работать с режимом hard, чтобы не допустить случайной и необратимой потери важных данных.

Хотите внести свой вклад?
Участвуйте в нашей контент-программе за
вознаграждение или запросите нужную вам инструкцию
img-server
21 августа 2024 г.
143
9 минут чтения
Средний рейтинг статьи: 5
Пока нет комментариев