Продвинутый Git: rebase, stash, reset и revert
git rebase — линейная история
git rebase переносит коммиты текущей ветки поверх другой:
git switch feature
git rebase main # перенести feature-коммиты на конец main
В отличие от merge, не создаёт merge-коммит. История получается линейной.
merge: C1 → C2 → C3 → C4 → C6 (merge commit)
↓ ↑
C5 ————————
rebase: C1 → C2 → C3 → C4 → C5' → C6'
Золотое правило: не перебазируй ветки, которые уже запушены и видны другим. Rebase создаёт новые хеши — у коллег сломается история.
Интерактивный rebase
git rebase -i HEAD~3 # редактировать последние 3 коммита
В редакторе можно:
pick— оставитьsquash— слить с предыдущимreword— изменить сообщениеdrop— удалить коммит
Используется для «причёсывания» истории перед PR: убрать WIP-коммиты, объединить мелкие правки.
git stash — карман для незаконченной работы
git stash # спрятать изменения
git stash push -m "feat: черновик" # с именем
git stash list # список
git stash pop # достать последний и удалить
git stash apply stash@{1} # достать конкретный, не удалять
git stash drop stash@{0} # удалить конкретный
Stash — стек (LIFO). Каждый git stash кладёт запись сверху стека.
Типичный сценарий:
git stash push -m "WIP: фича"
git switch main
git switch -c hotfix/bug
# ...фикс...
git commit && git push
git switch feature
git stash pop
git reset — переписать историю
git reset --soft HEAD~1 # убрать коммит → изменения в staging
git reset --mixed HEAD~1 # убрать коммит → изменения в working dir
git reset --hard HEAD~1 # убрать коммит → изменения УДАЛЕНЫ
Три режима — разная судьба изменений после отмены коммита.
Только для локальных веток (до push). После push история уже на remote — reset сломает коллег.
git revert — безопасная отмена
git revert HEAD # отменить последний коммит
git revert a3f7c21 # отменить конкретный
Создаёт новый коммит, который отменяет изменения. История не переписывается — безопасно для shared веток.
До: C1 → C2 → C3 (HEAD)
После: C1 → C2 → C3 → C4 (Revert "C3")
git restore — файлы без коммитов
git restore файл # отменить изменения в working dir
git restore --staged файл # убрать из staging
git restore --source HEAD~2 файл # взять файл из прошлого
git reflog — страховочная сетка
git reflog
Хранит все перемещения HEAD за 90 дней. Даже после --hard reset — коммиты не исчезли, они просто недостижимы. Через reflog можно найти их хеш и восстановить.
git reflog # найти нужный хеш
git reset --hard abc123 # вернуться
Когда что использовать
| Ситуация | Инструмент |
|---|---|
| Исправить последний коммит | git commit --amend |
| Отменить коммит (локально) | git reset --soft/--mixed HEAD~1 |
| Отменить коммит (после push) | git revert HEAD |
| Убрать файл из staging | git restore --staged файл |
| Откатить файл к версии из прошлого | git restore --source HASH файл |
| Спрятать незаконченное | git stash |
| Линейная история перед PR | git rebase main |
| Восстановить потерянный коммит | git reflog + git reset --hard HASH |