git branches

git revert

Создание нового коммита, отменяющего изменения указанного коммита

Описание

git revert создаёт новый коммит, который является «обратным» (инверсным) к указанному коммиту. В отличие от git reset, который удаляет коммиты из истории, git revert сохраняет всю историю нетронутой и добавляет новую запись об отмене. Это делает его безопасным для использования в общих (опубликованных) ветках.

Команда применяет «обратный diff» указанного коммита: если коммит добавил строку — revert её удалит, если удалил — добавит обратно. Если с момента отменяемого коммита прошло много изменений, могут возникнуть конфликты слияния, которые нужно разрешить вручную.

Основные сценарии использования: откат неудачного деплоя на production-ветке, отмена коммита, который был уже слит в main и отправлен на remote, удаление фичи, которая вызвала проблемы, без переписывания публичной истории.

Синтаксис

# Отменить конкретный коммит git revert <хеш-коммита> # Отменить последний коммит git revert HEAD # Отменить несколько коммитов (по одному revert-коммиту на каждый) git revert HEAD~3..HEAD # Отменить диапазон без промежуточных коммитов (один revert-коммит) git revert --no-commit HEAD~3..HEAD git commit -m "revert: remove broken feature X" # Отменить merge-коммит git revert -m 1 <хеш-merge-коммита> # Не открывать редактор (принять сообщение по умолчанию) git revert --no-edit HEAD # Продолжить после разрешения конфликтов git revert --continue # Прервать процесс revert git revert --abort

Флаги и опции

Флаг Описание
--no-edit Не открывать редактор для сообщения коммита — использовать автоматически сгенерированное сообщение «Revert "..."»
-n, --no-commit Применить изменения и добавить в индекс, но не создавать коммит. Позволяет собрать несколько revert-ов в один коммит.
-m <N> При отмене merge-коммита: указать номер родителя (1 = ветка-получатель, 2 = вливаемая ветка), изменения которого нужно сохранить
--continue Продолжить процесс revert после разрешения конфликтов и git add
--abort Отменить процесс revert и вернуть рабочий каталог в исходное состояние
--quit Прервать revert, оставив рабочий каталог как есть (без отката)
-e, --edit Открыть редактор для сообщения revert-коммита (включено по умолчанию)
-S, --gpg-sign GPG-подписать создаваемый revert-коммит
--signoff Добавить строку Signed-off-by в сообщение revert-коммита
--strategy Указать стратегию слияния при разрешении конфликтов (ort, recursive)

Паттерны использования

Откат последнего коммита на production

# Безопасная отмена опубликованного коммита
git revert HEAD --no-edit

# Или с кастомным сообщением
git revert HEAD
# В редакторе: "revert: rollback broken deploy #247"

git push origin main

Откат конкретного коммита из середины истории

# Найти коммит с багом
git log --oneline

# Отменить конкретный коммит
git revert abc1234

# Могут возникнуть конфликты — разрешить и:
git add .
git revert --continue

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

# Отменить последние 3 коммита одним revert-коммитом
git revert --no-commit HEAD~3..HEAD

# Все изменения собраны в индексе
git status

# Создать один итоговый коммит
git commit -m "revert: remove feature X (caused regression)"

Откат merge-коммита

# -m 1: оставить состояние главной ветки (main),
# отменить всё, что пришло из feature-ветки
git revert -m 1 <хеш-merge-коммита>

# -m 2 означало бы: оставить feature, отменить main
# (используется очень редко)

revert vs reset: когда что использовать

# revert: коммит уже опубликован на remote
# история должна быть сохранена
git revert HEAD
git push origin main

# reset: коммит ещё локальный
# можно переписать историю
git reset --soft HEAD~1
git push origin main  # НЕ нужен force-push

Восстановление после revert (re-apply)

# Если нужно "вернуть обратно отменённую фичу"
# revert of revert:
git revert <хеш-revert-коммита>

# Или cherry-pick оригинального коммита
git cherry-pick <хеш-оригинального-коммита>

Советы и подводные камни

revert — правильный инструмент для shared-веток: если коммит уже опубликован и другие разработчики могут на него опираться, всегда используйте git revert вместо git reset. Revert не переписывает историю, поэтому не вызывает проблем при git pull у других.
Автоматическое сообщение revert-коммита: Git генерирует сообщение в формате Revert "<исходное сообщение коммита>". Флаг --no-edit позволяет принять его без открытия редактора — удобно в скриптах или при массовом откате через --no-commit.
Отмена merge-коммита: будьте осторожны с повторным merge: после git revert -m 1 <merge-коммит>, если попытаться снова влить ту же feature-ветку — Git посчитает, что эти изменения уже в истории и ничего не добавит. Придётся сначала revert-нуть revert-коммит, и только потом делать повторный merge.