Перейти к основному содержимому

Отменить и отменить коммиты в Git

· 6 мин. чтения

Задача: Сумма двух

Дано массив целых чисел и целая сумма. Нужно найти индексы двух чисел, сумма которых равна заданной ...

ANDROMEDA

1. Введение

При использовании Git нам часто приходится отменять или возвращать фиксацию, будь то откат к определенному моменту времени или откат особенно проблемной фиксации. В этом руководстве мы рассмотрим наиболее распространенные команды для отмены и возврата коммитов в Git. Мы также продемонстрируем тонкие различия в том, как работают эти команды.

2. Просмотр старых коммитов с помощью git checkout

Начнем с того, что мы можем просмотреть состояние проекта при определенной фиксации с помощью команды git checkout . Мы можем просмотреть историю репозитория Git с помощью команды git log . Каждый коммит имеет уникальный идентификационный хэш SHA-1, который мы можем использовать с git checkout для повторного посещения любого коммита на временной шкале.

В этом примере мы вернемся к коммиту, который имеет идентификационный хэш e0390cd8d75dc0f1115ca9f350ac1a27fddba67d : ``

git checkout e0390cd8d75dc0f1115ca9f350ac1a27fddba67d

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

Мы можем использовать git checkout для локально измененных файлов, чтобы восстановить их версии рабочей копии .

3. Откат фиксации с помощью git revert

Мы отменяем коммит в Git с помощью команды git revert . Важно помнить, что эта команда не является традиционной операцией отмены. Вместо этого он инвертирует изменения, внесенные фиксацией, и создает новую фиксацию с обратным содержимым.

Это означает, что git revert следует использовать только в том случае, если мы хотим применить инверсию конкретного коммита . Он не возвращается к предыдущему состоянию проекта путем удаления всех последующих коммитов — он отменяет один коммит.

git revert не перемещает указатели ref на фиксацию, которую мы отменяем, в отличие от других команд «отмены», таких как git checkout и git reset . Вместо этого эти команды перемещают указатель HEAD ref на указанный коммит.

Давайте рассмотрим пример отмены коммита:

mkdir git_revert_example
cd git_revert_example/
git init .
touch test_file
echo "Test content" >> test_file
git add test_file
git commit -m "Adding content to test file"
echo "More test content" >> test_file
git add test_file
git commit -m "Adding more test content"
git log
git revert e0390cd8d75dc0f1115ca9f350ac1a27fddba67d
cat test_file

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

В данном случае мы откатываем самую последнюю фиксацию. Наконец, мы запустили git revert и убедились, что изменения в коммите были отменены, выведя содержимое файла.

4. Возврат к предыдущему состоянию проекта с помощью git reset

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

git reset похож на git checkout . Однако git reset будет перемещать указатель HEAD ref, тогда как git checkout работает с указателем HEAD ref и не перемещает его .

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

Первое дерево — это рабочий каталог . Это дерево синхронизировано с локальной файловой системой и представляет немедленные изменения, внесенные в содержимое файлов и каталогов.

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

Последнее дерево — это история коммитов . Команда git commit добавляет изменения в постоянный снимок, который хранится в истории коммитов .

4.1. -жесткий

Наиболее опасная и часто используемая опция с этим вызовом — это указатели ссылок на историю коммитов для обновления до указанного коммита. После этого промежуточный индекс и рабочий индекс сбрасываются, чтобы соответствовать указанному коммиту. Все ранее отложенные изменения промежуточного индекса и рабочего каталога сбрасываются в соответствии с состоянием дерева коммитов . Мы потеряем любую незавершенную или незафиксированную работу в промежуточном индексе и рабочем индексе .

Следуя приведенному выше примеру, давайте добавим еще немного контента в файл, а также зафиксируем новый файл в репозиторий:

echo "Text to be committed" >> test_file
git add test_file
touch new_test_file
git add new_test_file
git commit -m "More text added to test_file, added new_test_file"

Допустим, мы решили вернуться к первому коммиту в репозитории. Мы добьемся этого, выполнив команду:

git reset --hard 9d6bedfd771f73373348f8337cf60915372d7954

Git сообщит нам, что HEAD теперь находится в указанном хэше коммита. Глядя на содержимое test_file , мы видим, что наши последние текстовые добавления отсутствуют, а наш new_test_file больше не существует . Эта потеря данных необратима, поэтому очень важно, чтобы мы понимали, как –hard работает с тремя деревьями Git.

4.2. -мягкий

Когда вызов происходит с параметром –soft , указатели ref обновляются, и сброс останавливается на этом. Таким образом, промежуточный индекс и рабочий каталог остаются в том же состоянии.

В нашем предыдущем примере изменения, которые мы зафиксировали в промежуточном индексе , не были бы удалены, если бы мы использовали аргумент –soft . Мы по-прежнему можем зафиксировать наши изменения в промежуточном индексе .

4.3. смешанный

Режим работы по умолчанию, если аргумент не передан, –mixed предлагает промежуточный вариант между вызовами –soft и –hard . Промежуточный индекс сбрасывается до состояния указанного обновления указателей фиксации и ссылки. Любые отмененные изменения из промежуточного индекса перемещаются в рабочий каталог .

Использование –mixed в нашем примере выше означает, что наши локальные изменения в файлах не удаляются. Однако, в отличие от –soft , изменения в промежуточном индексе отменяются и ожидают дальнейших действий .

5. Вывод

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

git reset переместит указатель HEAD ref, тогда как git revert просто отменит фиксацию и применит отмену через новую фиксацию к HEAD . Также важно отметить, что мы никогда не должны использовать git reset , когда любые последующие снимки были отправлены в общий репозиторий . Мы должны предположить, что другие разработчики полагаются на опубликованные коммиты.