Перейти к содержанию

Отмена действий в Git#

Отмена изменений до git add#

Вернуть состояние файла к последнему коммиту.

git restore <path-to-dir-or-file>

Отмена изменений после git add до git commit#

Если нежелательные изменения уже проиндексированы, т. е. выполнена команда git add.

# Отменяет git add
git restore --staged <path-to-dir-or-file>
# Возвращает к исходному состоянию
git restore <path-to-dir-or-file>

Можно и одной командой.

git reset --hard <path-to-dir-or-file>

Отмена коммитов до git push#

Изменение последнего коммита#

Часто нужно что-то добавить/исправить/удалить в последнем коммите, в том числе сообщение коммита.

# Добавляем/исправляем/удаляем
# Индексируем изменения (git add)
git commit -m "New message" --amend 

Можно без -m и сообщения, если не хотим его менять, тогда надо будет просто закрыть открывшийся редактор, либо добавить флаг --no-edit, чтобы Git даже и не предлагал изменять сообщение.

# Добавляем/исправляем/удаляем
# Индексируем изменения (git add)
git commit --amend --no-edit

Коммит не должен быть запушен!

Команда git commit --amend изменяет историю репозитория, не нужно использовать её, если последний коммит уже оказался на сервере (была выполнена команда git push).

Удаление последних коммитов#

Можно полностью удалить коммит из истории репозитория с помощью git reset.

# Можно добавить --hard, чтобы откатить изменения и вернуть рабочий каталог
# к состоянию, в котором он был на предыдущем коммите
git reset HEAD~1

После такого удаления можно делать git push, не опасаясь, что кто-нибудь ещё сможет получить доступ к данным коммита, его следы могут остаться лишь в локальной копии репозитория.

Коммит не должен быть запушен!

Команда git reset изменяет историю репозитория, не нужно использовать её, если последний коммит уже оказался на сервере (была выполнена команда git push).

Подробнее про git reset

Команда git reset <commit> просто перемещает текущую ветку и HEAD на указанный коммит. Соответственно, вместо HEAD~1 (указатель на предыдущий коммит) можно указать любой другой коммит в текущей ветке, например, HEAD~3 - позволит отменить последние 3 коммита. Разумеется можно указать хэш коммита, к которому нужно откатиться.

Параметр --hard говорит о том, что нужно сбросить и индекс и рабочий каталог до состояния указанного коммита. Есть и другие варианты: --soft - оставить изменения в индексе и рабочем каталоге, --mixed (значение по умолчанию) - сбросить индекс, но не трогать рабочий каталог.

Как восстановить коммиты, удалённые с помощью git reset

Git ведёт локальный журнал всех операций, так что хэш коммита ещё можно восстановить.

git reflog

Зная хэш коммита, можно вернуть состояние ветки к нему с помощью того же git reset.

git reset <commit-hash>

Или, например, вынести его в отдельную ветку.

git checkout <commit-hash>
git checkout -b branch-with-restored-commit

Отмена коммитов после git push#

Отмена изменений последнего коммита#

Если коммит уже оказался в удалённом репозитории, то самый простой вариант - просто сделать новый коммит, который будет отменять изменения предыдущего.

git revert HEAD

Можно указать диапазон коммитов, которые нужно отменить, или перечислить их хэши.

# Создаст коммит с отменой изменений последних трёх коммитов
git revert HEAD~3..HEAD

После git revert можно спокойно делать git push, не опасаясь, что возникнут какие-либо конфликты с удалённым репозиторием.

Изменения сохраняются в репозитории

Никакие данные ни из локального, ни из удалённого репозитория не удаляются, все коммиты остаются в истории той же самой ветки. git revert не подходит, если нужно полностью удалить нежелательные изменения (например, конфиденциальные данные) из локального и удалённого репозитория.

Удаление последних коммитов из удалённого репозитория#

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

Для отмены коммитов можно использовать методы, описанные в предыдущем разделе, а затем перезаписать историю удалённого репозитория.

git push --force

Полезные ссылки#