Прятанье незавершённой работы
git stash прячет незакоммиченные отслеживаемые изменения и даёт чистое дерево, чтобы переключить ветку посреди работы. pop возвращает и удаляет запись; apply возвращает, но оставляет её. Заначки образуют стек, который можно смотреть и удалять, но они локальны и легко забываются.
Ты на полпути через фичу, файлы повсюду, коммитить нечего — и тут прилетает продакшен-баг, который надо чинить в main прямо сейчас. Git отказывается переключать ветку, потому что checkout затрёт твои правки. Коммитить полусломанный код только ради переключения не хочется. Для ровно этого случая есть парковка: git stash.
К концу этого урока ты сможешь отложить грязные изменения, чтобы получить чистое дерево, сменить контекст и вернуть работу обратно — точно зная, чем различаются pop и apply и где заначка на самом деле живёт.
После этого урока ты сможешь с помощью git stash отложить незавершённую работу и восстановить её, объяснить стек заначек и разницу между pop и apply, а также избегать классических ловушек с неотслеживаемыми файлами и забытыми заначками.
git stash записывает твои незакоммиченные отслеживаемые изменения и сбрасывает рабочее дерево к HEAD. Он берёт всё изменённое-и-отслеживаемое — и проиндексированное, и нет — сохраняет это как скрытый объект вроде коммита и откатывает файлы к чистому состоянию, совпадающему с последним коммитом:
git stash # сокращение от: git stash push
git status # теперь чисто — правки припаркованы, а не потеряныКлючевая идея: ты получаешь чистое дерево без коммита и без потери работы. Теперь git switch main срабатывает.
Заначки образуют стек, и его можно посмотреть. Каждый git stash кладёт новую запись наверх, нумерация от самой свежей:
git stash list
# stash@{0}: WIP on feature: 9f3c1a2 Add filter UI
# stash@{1}: WIP on feature: 9f3c1a2 Add filter UIstash@{0} — самая новая. Поскольку автоматические сообщения выглядят одинаково, давай заначкам имена, чтобы будущий ты их различал:
git stash push -m "наполовину готовая валидация фильтра"pop возвращает и удаляет; apply возвращает и оставляет. Чтобы вернуть работу:
git stash pop # вернуть stash@{0}, затем удалить его из стека
git stash apply # вернуть stash@{0}, но ОСТАВИТЬ его в стеке
git stash apply stash@{1} # вернуть конкретную старую записьИспользуй pop для обычного случая «продолжить с того места, где остановился». Используй apply, когда хочешь то же изменение на нескольких ветках или когда нервничаешь из-за конфликтов и хочешь страховочную копию, пока не убедишься, что всё легло чисто.
▸Граничные случаи
По умолчанию git stash игнорирует неотслеживаемые файлы (новые файлы, которых git ещё не видел) и игнорируемые. Поэтому новенький config.local.js остаётся в рабочем дереве даже после stash — и может заблокировать то самое переключение ветки, ради которого ты всё затевал. Добавь -u (--include-untracked), чтобы захватить и новые файлы, или -a (--all), чтобы включить ещё и игнорируемые. Забыть про это — самый частый сюрприз «но я же всё спрятал!».
pop может упасть с конфликтом — и тогда заначку он не удаляет. Если ветка ушла вперёд и спрятанное изменение пересекается, возврат порождает конфликты слияния. Разреши их как любое слияние, затем git add файлы. Заметь, что конфликтный pop оставляет запись заначки (чтобы ты не потерял её посреди конфликта); удали её сам после разрешения. Ещё два полезных инструмента:
git stash drop stash@{1} # удалить одну запись, не применяя её
git stash branch fix-wip # создать ветку ИЗ заначки и применить её тамgit stash branch — чистый запасной выход, когда заначка больше не применяется к текущей ветке: он переключается на коммит, на котором заначка была сделана, так что изменение ложится без конфликта.
Экстренный хотфикс, от начала до конца.
Ты на feature/search с десятком изменённых файлов и одним новым файлом search.test.js, которого git никогда не отслеживал. Алерт пейджера говорит, что checkout сломан на main.
git stash push -u -m "search WIP + новый тест" # -u чтобы новый файл теста тоже ушёл
git switch main
# ... чинишь продакшен-баг, коммитишь, пушишь ...
git switch feature/search
git stash popПосле pop все двенадцать правок и новый файл теста на месте — ровно так, как ты их оставил, а стек заначек снова пуст. Если бы pop сообщил о конфликте (скажем, хотфикс из main тоже трогал открытый у тебя файл), ты разрешил бы его, сделал git add результата, затем git stash drop, чтобы убрать запись, которую оставил конфликтный pop.
▸Частая ошибка
Заначка локальна и невидима для всех остальных. Она не часть какого-либо коммита, никогда не пушится и не появляется в git log. Люди регулярно прячут что-то «на минутку», начинают новую работу и забывают про это на недели — а потом git stash list вскрывает кучу недоделанных записей. Относись к заначке как к недолгой парковке, а не хранилищу: если работа важна дольше, чем на полдня, сделай вместо этого коммит на ветке.
Ты хочешь применить спрятанное изменение по очереди на двух разных ветках. Какую команду использовать и почему?
git stash прячет твои незакоммиченные отслеживаемые изменения и выдаёт чистое рабочее дерево, чтобы можно было переключить ветку или сделать pull, не коммитя недоделанную работу. Заначки складываются в стек (stash@{0} — самая новая), который можно list, именовать через -m и drop. pop возвращает и удаляет запись; apply возвращает, но оставляет её для повторного использования. Помни про -u для неотслеживаемых файлов, про то, что конфликтный pop оставляет запись на месте, и что заначки локальны и легко забываются. Дальше ты скопируешь один коммит с одной ветки на другую с помощью git cherry-pick.
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.