↓Перейти к содержанию
  1. Git: руководства и команды/

git revert: безопасная отмена коммитов в Git

·4 минуты·

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

Что такое revert и как он работает #

Когда вы делаете git revert <hash>, Git вычисляет «обратные» изменения для указанного коммита и создаёт новый коммит с этими изменениями. Результат: исходный коммит остаётся в истории, но его эффект отменён.

До revert:  C1 - C2 - C3 - C4
                  ↑
            хотим отменить C2

После revert:  C1 - C2 - C3 - C4 - C2'(revert of C2)

Коммит C2' содержит обратные изменения относительно C2. История не нарушена, и другие разработчики могут продолжать работать с репозиторием без проблем.

Revert vs Reset: когда использовать что #

Это важнейший выбор при отмене коммитов:

Используйте git reset (переписывает историю):

  • Коммит только у вас локально, не отправлен в origin
  • Вы единственный разработчик в проекте
  • Ветка временная и её никто не видел

Используйте git revert (сохраняет историю):

  • Коммит уже в origin (отправлен)
  • Другие разработчики работают с этой веткой
  • Нужно документировать факт отмены изменений
  • Работаете в команде
# Локальная ветка — можно reset
git reset --hard HEAD~1

# Опубликованная ветка — только revert
git revert a1b2c3d

Простой revert одного коммита #

# Посмотреть историю для нахождения нужного коммита
git log --oneline

# Выполнить revert
git revert a1b2c3d

# Git откроет редактор с сообщением коммита
# По умолчанию: 'Revert "Исходное сообщение коммита"'
# Сохраните и закройте редактор

# Revert без открытия редактора
git revert --no-edit a1b2c3d

# Revert последнего коммита
git revert HEAD

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

a1b2c3d Добавить новую функцию
...
f5e6d7c Revert "Добавить новую функцию"

Revert нескольких коммитов #

Если нужно отменить несколько коммитов:

# Отменить три последних коммита (создаст 3 revert-коммита)
git revert HEAD~2..HEAD

# Отменить диапазон (исключающий — a1b2c3d не включается)
git revert a1b2c3d..e4f5g6h

# Отменить диапазон (включающий)
git revert a1b2c3d^..e4f5g6h

# Отменить несколько отдельных коммитов
git revert a1b2c3d b4c5d6e c5d6e7f

Для каждого коммита Git откроет редактор с сообщением. Чтобы избежать этого:

# Revert нескольких коммитов без подтверждения каждого
git revert --no-edit HEAD~2..HEAD

Revert без автоматического коммита #

Если хотите проверить или изменить результат revert перед коммитом:

# Применить изменения, но не коммитить
git revert -n a1b2c3d
# или
git revert --no-commit a1b2c3d

# Теперь изменения в индексе, можно проверить
git status
git diff --staged

# Можно дополнить или изменить
# Затем закоммитить с кастомным сообщением
git commit -m "Отмена проблемного изменения + дополнительная правка"

Revert для merge-коммитов #

Отмена merge-коммита требует дополнительного параметра -m, который указывает «родительский» коммит:

# Просмотреть merge commit
git show a1b2c3d
# В выводе будет строка: Merge: parent1 parent2

# Revert merge commit
# -m 1 означает оставить изменения из первого родителя (main branch)
git revert -m 1 a1b2c3d

# -m 2 означает оставить изменения из второй ветки
git revert -m 2 a1b2c3d

Обычно используется -m 1, чтобы вернуться к состоянию основной ветки до merge.

Разрешение конфликтов при revert #

Если revert затрагивает те же строки, что были изменены после отменяемого коммита, возникнет конфликт:

git revert a1b2c3d
# CONFLICT (content): Merge conflict in src/auth.js

# Разрешить конфликты в файлах
git status
# Открыть файлы, убрать маркеры <<<, ===, >>>
git add src/auth.js

# Продолжить revert
git revert --continue

# Или отменить revert
git revert --abort

Практические примеры #

# Посмотреть изменения коммита перед revert
git show a1b2c3d

# Отмена последнего коммита
git revert HEAD --no-edit

# Отмена конкретного коммита
git revert a1b2c3d

# Отмена нескольких коммитов без подтверждений
git revert --no-edit HEAD~3..HEAD

# Revert без коммита для объединения с другими изменениями
git revert -n a1b2c3d
git revert -n b2c3d4e
git commit -m "Отменить два ошибочных изменения"

# Revert merge-коммита
git revert -m 1 a1b2c3d

# Отменить сам revert (если revert был ошибочным)
git revert <hash-of-revert-commit>

# Найти revert-коммиты в истории
git log --oneline | grep -i revert

Часто задаваемые вопросы #

Когда использовать revert вместо reset? Используйте revert, когда ветка уже опубликована (в origin) и другие разработчики работают с ней. Reset переписывает историю и вызовет проблемы у других. Revert безопасен всегда.

Что произойдёт при revert merge-коммита? Нужно указать родительскую ветку через -m 1 или -m 2. Без этого Git не знает, «откуда» смотреть на изменения. Обычно -m 1 возвращает к состоянию основной ветки.

Как разрешить конфликты при revert? Так же как при merge: открыть конфликтный файл, выбрать нужную версию, убрать маркеры, git add <file>, затем git revert --continue.

Можно ли отменить revert? Да — через git revert <hash-of-revert-commit>. Это создаст ещё один коммит, отменяющий сам revert. История станет длиннее, но безопасность сохранится.

Как revert работает с несколькими коммитами? Git создаёт отдельный revert-коммит для каждого отменяемого коммита. Используйте -n (no-commit) и затем один git commit, чтобы объединить их в один revert-коммит.

Заключение #

git revert — правильный инструмент для отмены опубликованных коммитов. Он сохраняет историю, документирует факт отмены и безопасен для командной работы. Для локальных коммитов — используйте git reset. История всех операций доступна через git log.

По теме #