← назад к разделу

Главная правда о Git, которую стоит выучить до первой паники: закоммиченное почти невозможно потерять. У каждой ошибки есть штатная отмена, а на крайний случай существует reflog — чёрный ящик, помнящий всё. Разберём инструменты от лёгких случаев к тяжёлым.

Отменить незакоммиченное: restore

git restore file.txt            # откатить файл к последнему коммиту (правки ПРОПАДУТ)
git restore --staged file.txt   # убрать из индекса (правки останутся в файле)
git restore .                   # откатить всё незакоммиченное

Единственное место в Git, где работа теряется по-настоящему, — здесь: незакоммиченные правки после restore не вернуть. Отсюда правило: сомневаетесь — сначала закоммитьте или спрячьте в stash, откатить сможете всегда.

Спрятать на минутку: stash

Нужно срочно переключиться, а работа не доделана:

git stash                # спрятать незакоммиченное в карман
git stash list           # что в кармане
git stash pop            # вернуть последнее спрятанное

Stash — временный карман, не архив: вернулись к задаче — сразу pop. Полгода коллекционировать stash'и — способ забыть, что в них было.

Откатить коммиты: reset против revert

Два инструмента для разных ситуаций — граница проходит по вопросу «отправлено ли это уже другим?»

reset — переписать локальную историю (коммиты ещё не пушены):

git reset --soft HEAD~1   # снять последний коммит, изменения остаются в индексе
git reset HEAD~1          # снять коммит, изменения — в рабочих файлах (по умолчанию)
git reset --hard HEAD~1   # снять коммит И ВЫБРОСИТЬ изменения

--soft — «пересобрать коммит иначе», --hard — «этого не было». С --hard — как с UPDATE без WHERE: сначала убедитесь, что выбрасываете именно то.

revert — отменить публично и честно (коммиты уже на сервере):

git revert a1b2c3    # создаёт НОВЫЙ коммит с обратными изменениями

История не переписывается — она дополняется коммитом-антиподом. Именно так откатывают влитое в main: сломавший прод PR отменяется revert-коммитом за минуту, безопасно и с сохранением летописи. Правило в одну строку: локальное — reset, отправленное — revert.

reflog: машина времени последней надежды

«Сделал reset --hard не туда», «rebase всё сломал», «удалил ветку с работой» — спокойно. Reflog — журнал всех перемещений HEAD за последние ~90 дней, включая «удалённые» состояния:

git reflog
# a1b2c3 HEAD@{0}: reset: moving to HEAD~3
# d4e5f6 HEAD@{1}: commit: та самая работа   ← вот оно!

git reset --hard d4e5f6      # вернуться в состояние до аварии
# или аккуратнее: git branch rescue d4e5f6 — поставить ветку на найденный коммит

Всё, что хоть раз было закоммичено, находится в reflog. Настоящих способов потерять закоммиченную работу почти нет — и это возвращает к правилу из начала цикла: коммитьте часто; коммит — это страховка, которую нельзя отобрать.

Коротко

  • Незакоммиченное — единственное по-настоящему теряемое: restore необратим. Сомневаетесь — коммит или stash.
  • stash — карман на минутку: спрятал → переключился → вернулся → pop.
  • Локальную историю правит reset (soft — пересобрать, hard — выбросить); отправленную отменяет revert новым коммитом. «Локальное — reset, публичное — revert».
  • reflog помнит все состояния ~90 дней: после любой аварии — git reflog → вернуться на нужный коммит.
  • Частые коммиты = неотбираемая страховка.

Что почитать дальше

  • Rebase и cherry-pick — операции, после которых reflog особенно греет душу.
  • Коммиты и история — --amend и другие лёгкие правки.
  • Модели ветвления — финальная статья цикла.