Инструкция

git stash: как временно отложить изменения и вернуть их

Обновлено: · Skillaria.Top

git stash убирает незакоммиченные изменения в отдельное хранилище и возвращает рабочую папку к последнему коммиту, чтобы вы могли переключиться на другую задачу. Вернуть правки можно командой git stash pop (применить и удалить из хранилища) или git stash apply (применить и оставить); отдельной команды git unstash нет.

Зачем нужен git stash

Типичная ситуация: вы на середине задачи, файлы изменены, коммитить рано — и тут просят срочно поправить баг в другой ветке. Переключиться не получается или страшно потерять правки. git stash складывает все незакоммиченные изменения «в карман» и возвращает рабочую папку к состоянию последнего коммита.

$ git stash
Saved working directory and index state WIP on feature/login: 3f2a1c4 Форма входа

$ git status
On branch feature/login
nothing to commit, working tree clean

Теперь можно переключиться, исправить баг, вернуться и достать отложенное. Каждое сохранение — это запись в стеке stash, внутри Git хранит её как особый коммит, поэтому данные надёжны и не зависят от ветки.

Как сохранить изменения: основные варианты

С понятным описанием

Стандартное описание «WIP on ветка» через неделю ничего не скажет. Подписывайте:

git stash push -m "валидация формы, не доделан e-mail"

git stash без аргументов — это сокращение для git stash push. Устаревшая форма git stash save "сообщение" ещё работает, но в новых сценариях используйте push -m.

Вместе с новыми файлами

По умолчанию stash забирает только отслеживаемые файлы — изменённые и добавленные в индекс. Новые файлы, которые ещё ни разу не были в git add, остаются в рабочей папке. Это частый сюрприз.

git stash -u        # --include-untracked: плюс неотслеживаемые файлы
git stash -a        # --all: плюс файлы из .gitignore

С -a осторожнее: в карман уедут и node_modules, и сборки, и локальные конфиги. Обычно хватает -u.

Только часть изменений

git stash push -m "конфиг" src/config.js   # только указанные файлы
git stash -p                                # выбрать фрагменты интерактивно
git stash --staged                          # только то, что в индексе (Git 2.35+)
git stash --keep-index                      # отложить всё, но оставить индекс в папке

--keep-index полезен перед коммитом: вы оставляете в рабочей папке только то, что собираетесь закоммитить, прогоняете тесты и убеждаетесь, что коммит самодостаточен.

Как вернуть изменения (git unstash)

Команды git unstash в Git не существует — так обычно ищут способ достать отложенное. Для этого есть две команды.

КомандаЧто делаетЗапись в стеке
git stash popПрименяет последние отложенные измененияУдаляется, если применилось без конфликтов
git stash applyПрименяет последние отложенные измененияОстаётся
git stash pop stash@{2}Применяет конкретную записьУдаляется
git stash apply --indexВосстанавливает и разделение на индекс и рабочую папкуОстаётся
$ git stash pop
On branch feature/login
Changes not staged for commit:
        modified:   src/auth.js
        modified:   src/form.js
Dropped refs/stash@{0} (8c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d)

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

pop или apply

Для повседневной работы удобен pop: достали и забыли. apply выбирайте, когда хотите применить одни и те же изменения в нескольких ветках или не уверены, что всё пройдёт гладко, — запись останется страховкой, а удалить её можно потом через git stash drop.

Работа со списком отложенного

$ git stash list
stash@{0}: On feature/login: валидация формы, не доделан e-mail
stash@{1}: WIP on main: 9b7e0d2 Обновить зависимости
stash@{2}: On feature/api: эксперимент с кэшем

Стек работает по принципу «последним положил — первым достал»: stash@{0} всегда самая свежая запись, и номера сдвигаются после каждого push и drop.

КомандаНазначение
git stash showКраткая статистика изменений последней записи
git stash show -p stash@{1}Полный diff конкретной записи
git stash drop stash@{1}Удалить одну запись
git stash clearУдалить все записи разом
git stash branch имя stash@{0}Создать ветку от коммита, на котором делался stash, применить запись и удалить её

Чтобы git stash show по умолчанию показывал не статистику, а полный diff и заодно неотслеживаемые файлы, есть настройки stash.showPatch и stash.showIncludeUntracked.

Пошаговый сценарий: срочный баг посреди задачи

  1. Отложите текущую работу вместе с новыми файлами: git stash push -u -m "логин: черновик".
  2. Переключитесь на основную ветку и создайте ветку для исправления: git switch main, git pull, git switch -c hotfix/null-email.
  3. Исправьте ошибку, закоммитьте, отправьте на ревью.
  4. Вернитесь к задаче: git switch feature/login.
  5. Достаньте правки: git stash pop. Проверьте git status — всё на месте.

Сейчас многие для этого сценария используют git worktree: вторая рабочая папка для той же репы позволяет вообще ничего не откладывать. Но для быстрого переключения на пять минут stash по-прежнему проще.

Конфликты при применении stash

Если после stash в ветке изменились те же строки, применение закончится конфликтом:

$ git stash pop
Auto-merging src/auth.js
CONFLICT (content): Merge conflict in src/auth.js
The stash entry is kept in case you need it again.

Запись в этом случае не удаляется, даже при pop. Разрешите конфликт в файле как обычно, затем выполните git add для пометки решения (или git restore --staged, если не хотите оставлять изменения в индексе) и удалите ставшую ненужной запись через git stash drop.

Если конфликт сложный, удобнее обходной путь: git stash branch tmp-login. Git создаст ветку от того самого коммита, на котором вы делали stash, — там изменения применятся без конфликтов, а с основной веткой вы их сольёте уже обычным merge.

Как восстановить случайно удалённый stash

Выполнили git stash drop или clear по ошибке — не всё потеряно. Запись была коммитом, и пока сборщик мусора его не удалил, его можно найти среди «висячих» объектов:

git fsck --no-reflog | grep "dangling commit"
git show 8c1d2e3        # проверить, тот ли это stash
git stash apply 8c1d2e3

Если вы только что удалили запись через drop или pop, хеш напечатан прямо в выводе команды — в строке Dropped refs/stash@{0} (...). Его достаточно передать в git stash apply.

Как stash устроен внутри

Понимание устройства снимает страх потерять данные. Каждая запись stash — это обычный коммит, на который указывает ссылка refs/stash. У него два родителя: коммит HEAD, на котором вы стояли, и отдельный коммит с состоянием индекса. При -u добавляется третий родитель с неотслеживаемыми файлами. Список stash@{N} — это просто журнал (reflog) ссылки refs/stash.

Отсюда несколько практических следствий. Stash можно передать любой команде, которая принимает коммит: git diff stash@{0}, git show stash@{0}:src/auth.js (содержимое одного файла из записи) или git checkout stash@{0} -- src/auth.js, чтобы достать один файл, не применяя всю запись. А удалённая запись остаётся в базе объектов, пока её не уберёт сборка мусора.

Stash и другие команды Git

Некоторые команды умеют прятать изменения сами. git rebase --autostash и git pull --rebase --autostash перед началом откладывают незакоммиченные правки и возвращают их после окончания. Включить это поведение постоянно можно настройками rebase.autoStash true и merge.autoStash true. Если при возврате возникнет конфликт, Git сохранит запись в обычном стеке stash и сообщит об этом.

Переключение веток через git switch тоже не всегда требует stash: если ваши изменения не пересекаются с файлами, которые отличаются между ветками, Git просто перенесёт их с собой. Stash нужен, когда Git отвечает «Your local changes would be overwritten by checkout» или когда вы не хотите тащить правки в другую ветку.

Типичные ошибки

  • Новые файлы «не спрятались». Они не отслеживаются, нужен -u.
  • Stash как долговременное хранилище. Через месяц в списке десять безымянных «WIP on main», и никто не помнит, что там. Для долгой работы делайте коммит в отдельной ветке — его хотя бы можно запушить.
  • Забыли, что запись осталась после конфликта, и спустя время применили её ещё раз. После разрешения конфликта всегда делайте drop.
  • Stash не синхронизируется с сервером. Он хранится только в вашем локальном репозитории, git push его не отправляет. При удалении папки проекта stash пропадёт.
  • Применили не ту запись. Перед pop посмотрите git stash list и git stash show -p.

Итог

git stash — быстрый способ освободить рабочую папку, не теряя незакоммиченных правок: git stash push -u -m "описание", чтобы отложить, и git stash pop, чтобы вернуть. Используйте apply, когда нужна страховка, git stash list и show -p, чтобы не запутаться, и не превращайте stash в склад — для всего долгого есть коммиты и ветки. Переключение между задачами со stash отрабатывается на практике в курсе по Git.

Частые вопросы

Можно ли применить stash в другой ветке?

Да, stash не привязан к ветке: переключитесь в нужную и выполните git stash pop или apply. Если изменения не накладываются, возникнет обычный конфликт.

Сохраняет ли git stash изменения в индексе?

Сохраняет, но при обычном pop или apply всё вернётся как неподготовленные изменения. Чтобы восстановить и индекс, используйте git stash apply --index.

Сколько записей можно хранить в stash?

Жёсткого ограничения нет, но записи старше срока хранения reflog могут быть удалены при сборке мусора. На практике держите в стеке не больше пары свежих записей.

Как сделать stash одного файла?

Укажите путь после двух дефисов или прямо после push: git stash push -m описание -- src/config.js. В stash уйдёт только этот файл, остальные правки останутся в рабочей папке.

Чем stash отличается от временного коммита?

Коммит живёт в ветке, его можно отправить на сервер и потом поправить через amend или rebase. Stash хранится только локально в отдельном стеке и удобен для коротких переключений.

Разберите тему на видео

Эта тема подробно разобрана с практикой в курсе «Git с нуля до уверенного разработчика».

Перейти к курсу