Типичная ситуация: правишь файлы, не готов коммитить, и тут срочно нужно переключиться на другую ветку - посмотреть PR, починить hotfix. Не хочется ни коммитить «WIP», ни терять работу.
git stash отдаст рабочее дерево в специальный «карман», после
чего можно переключаться и работать. Когда вернёшься -
git stash pop восстановит правки.
Базовый цикл
git stash # спрячь текущие правки
git switch hotfix # переключись куда нужно
# ... поработать ...
git switch feature # вернись на ветку
git stash pop # верни правки
По умолчанию stash забирает и working tree, и индекс (всё
кроме untracked файлов). Чтобы включить untracked:
git stash -u # + untracked
git stash -a # + untracked + ignored (всё подряд)
С сообщением
Без сообщения stash получит auto-имя «WIP on feature: abc123 last commit subject». Это плохо читается. Лучше с описанием:
git stash push -m "поправил auth, не доделал logout"
Список и просмотр
git stash list
# stash@{0}: On feature: поправил auth, не доделал logout# stash@{1}: WIP on main: 7c8a1 fix typogit stash show stash@{0} # сводкаgit stash show -p stash@{0} # полный diffpop vs apply
git stash pop- применить и удалить из списка.git stash apply- применить, оставить в списке.
Apply удобен, если stash может пригодиться ещё раз. Pop - когда знаешь, что больше не понадобится.
По умолчанию обе команды берут stash@{0} (самый свежий). Можно
указать другой:
git stash pop stash@{2}stash branch
Если после stash ветка ушла далеко и pop приводит к конфликтам - можно достать stash как отдельную ветку:
git stash branch fix-from-stash stash@{0}Создаст ветку из коммита, на котором stash был сделан, и применит stash в чистой среде. Дальше можно нормально работать и сливать.
Что физически
Stash entry - это merge-коммит в refs/stash (не видим в обычных
branch listings). У него минимум два родителя:
- первый - HEAD на момент stash;
- второй - коммит снимка индекса.
С -u / -a добавляется ещё один родитель - коммит со снимком
untracked (и ignored) файлов. Итого в .git/objects/ под один
git stash ложится 3-4 объекта. Stash можно восстановить через
reflog даже после stash drop (по stash@{N} SHA).
Подводные камни
- Stash без
-uне прячет untracked. Untracked-файлы не «теряются» - они остаются в working tree, как лежали. Просто кажется, что «всё спрятано», а послеgit switchилиgit checkout .эти файлы видны в новом контексте. Если хочешь реально убрать untracked -git stash -u. - pop с конфликтом не удаляет stash. Если применение упало
в конфликт, stash остаётся в списке. После разрешения нужно
git stash drop stash@{0}руками.- Долго живущий stash - антипаттерн. Чем дольше stash лежит, тем больше main уходит вперёд, тем больнее pop. Если работа важна - лучше сделать ветку и коммит.
git stash clearудаляет всё без подтверждения. Если нужно очистить - лучшеgit stash dropпо одному, чтобы случайно не потерять.