← Вернуться в блог

Как отменить коммит Git (не потеряв работу)

tutorial git

Вы сделали commit, который хотите отменить. Что теперь?

Это случается с каждым. Вы делаете commit слишком рано, включаете файл, который не следовало, пишете неправильное сообщение или понимаете, что код просто не подходит. Хорошая новость: Git создан для таких ситуаций. Ещё лучшая новость: в большинстве случаев вы можете отменить commit, не потеряв свою работу.

Правильный подход зависит от одного ключевого вопроса: был ли commit push на remote, или он ещё локальный? Локальные commit дают больше гибкости. Push commit требуют более безопасной стратегии, потому что другие люди могли уже pull ваши изменения.

Отмена локального commit с помощью git reset

Если commit ещё локальный (не push), git reset — самый распространённый инструмент. Он перемещает указатель branch назад к предыдущему commit, фактически «отменяя» ваш commit. Что произойдёт с изменениями, зависит от используемого флага.

git reset --soft: отмена commit, всё остаётся в staging

git reset --soft HEAD~1

Это отменяет последний commit, но сохраняет все изменения в staging (в индексе). Ваша рабочая директория не затрагивается. Как будто вы никогда не выполняли git commit — вы возвращаетесь к моменту прямо перед commit.

Когда использовать: Вы хотите изменить сообщение commit, добавить больше файлов в commit или разделить commit на более мелкие. Ваш код в порядке, вы просто сделали commit преждевременно.

git reset --mixed: отмена commit, снятие изменений со staging

git reset --mixed HEAD~1

Это поведение git reset по умолчанию (флаг --mixed можно опустить). Отменяет commit и снимает изменения со staging, но файлы остаются изменёнными в рабочей директории. Ничего не теряется.

Когда использовать: Вы хотите пересмотреть, что включить в commit. Возможно, вы хотите добавить в staging только некоторые файлы или просмотреть изменения перед повторным commit.

git reset --hard: отмена commit, удаление всех изменений

git reset --hard HEAD~1

Это отменяет commit и безвозвратно удаляет все изменения. Ваша рабочая директория сбрасывается до состояния предыдущего commit. Восстановить удалённые изменения обычными операциями Git невозможно.

Когда использовать: Вы уверены, что изменения вам вообще не нужны. Возможно, вы закоммитили экспериментальный код, который не сработал, и хотите начать с чистого листа. Используйте с осторожностью.

Откат дальше назад

HEAD~1 указывает на один commit до текущего HEAD. Можно откатиться дальше:

git reset --soft HEAD~3

Это отменяет последние три commit, объединяя все их изменения в области staging. Также можно указать конкретный commit по его хешу:

git reset --soft a1b2c3d

Исправление последнего commit с помощью git commit --amend

Если нужно просто подправить последний commit, а не полностью отменять его, --amend — самый быстрый вариант:

git commit --amend -m "corrected commit message"

Это заменяет предыдущий commit новым. Также можно использовать для добавления забытых файлов:

git add forgotten-file.ts
git commit --amend --no-edit

Флаг --no-edit сохраняет оригинальное сообщение commit. Результат — один исправленный commit вместо последовательности «ой» commit.

Важно: Как и reset, amend переписывает историю. Используйте его только для commit, которые не были push. Если вы сделаете amend push commit и затем force-push, у всех, кто pull оригинальный commit, возникнут проблемы.

Отмена push commit с помощью git revert

Как только commit push на общий remote, вы не должны переписывать историю. Другие разработчики могли основать свою работу на этом commit. Вместо этого используйте git revert:

git revert HEAD

Это создаёт новый commit, который делает прямо противоположное целевому commit. Если оригинальный commit добавил строку, revert commit удаляет её. Если он удалил файл, revert commit восстанавливает его. Оригинальный commit остаётся в истории, а revert добавляется поверх.

Когда использовать: Каждый раз, когда нужно отменить commit, который уже был push. Это безопасно, потому что добавляет к истории, а не переписывает её.

Revert более старого commit

Можно сделать revert любого commit, не только самого последнего:

git revert a1b2c3d

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

Revert нескольких commit

Чтобы сделать revert диапазона commit:

git revert HEAD~3..HEAD

Это создаёт отдельные revert commit для каждого commit в диапазоне. Если вы предпочитаете один revert commit, добавьте флаг --no-commit и сделайте commit вручную:

git revert --no-commit HEAD~3..HEAD
git commit -m "revert last 3 commits"

Выбор правильного подхода

Ситуация Метод Что происходит с вашими изменениями
Commit слишком рано, нужно снова staging git reset --soft HEAD~1 Изменения остаются в staging
Commit слишком рано, нужно переработать git reset --mixed HEAD~1 Изменения остаются в рабочей директории
Commit того, что нужно отбросить git reset --hard HEAD~1 Изменения удалены
Нужно исправить сообщение или добавить файл git commit --amend Предыдущий commit заменён
Нужно безопасно отменить push commit git revert HEAD Новый commit отменяет изменения

Восстановление после ошибок

Даже если вы использовали git reset --hard и поняли, что не следовало этого делать, часто есть способ восстановиться. Git ведёт журнал того, куда указывал HEAD, называемый reflog:

git reflog

Это показывает список недавних позиций HEAD. Вы можете найти commit, который считали потерянным, и вернуться к нему:

git reset --hard HEAD@{2}

Reflog — это ваша страховочная сетка. Записи хранятся по умолчанию 90 дней, так что у вас есть достаточно времени для восстановления после ошибок.

Отмена commit в GitSquid

GitSquid упрощает наиболее распространённые операции отмены. Вы можете нажать Cmd+Z (или Ctrl+Z в Windows и Linux) сразу после commit, чтобы отменить последний commit, сохранив изменения в staging и готовыми к доработке. Для более конкретных операций щелчок правой кнопкой мыши по любому commit в графе открывает доступ к опциям reset и revert через контекстное меню, позволяя точно указать commit, который вы хотите отменить, без запоминания флагов.

Отмена commit в Git не должна быть стрессовой. Поймите разницу между reset, amend и revert, знайте, что подходит для вашей ситуации, и вы сможете уверенно исправлять ошибки. Самое важное различие простое: если это локально — reset или amend. Если push — revert.