Spec-Zone.ru › Git

git-stash

Название

git-stash — сохранение изменений из грязного рабочего каталога в stash

Краткое описание

git stash list [<log-options>]
git stash show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]
git stash drop [-q | --quiet] [<stash>]
git stash pop [--index] [-q | --quiet] [<stash>]
git stash apply [--index] [-q | --quiet] [--label-ours=<label>] [--label-theirs=<label>] [--label-base=<label>] [<stash>]
git stash branch <branchname> [<stash>]
git stash [push] [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
             [-u | --include-untracked] [-a | --all] [(-m | --message) <message>]
             [--pathspec-from-file=<file> [--pathspec-file-nul]]
             [--] [<pathspec>…​]
git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | --quiet]
           [-u | --include-untracked] [-a | --all] [<message>]
git stash clear
git stash create [<message>]
git stash store [(-m | --message) <message>] [-q | --quiet] <commit>
git stash export (--print | --to-ref <ref>) [<stash>…​]
git stash import <commit>

Описание

Используйте git stash, если хотите записать текущее состояние рабочего каталога и индекса, но при этом вернуться к чистому рабочему каталогу. Команда сохраняет ваши локальные изменения и приводит рабочий каталог в соответствие с коммитом HEAD.

Сохранённые этой командой изменения можно просмотреть с помощью git stash list, проверить с помощью git stash show и восстановить (возможно, поверх другого коммита) с помощью git stash apply. Вызов git stash без аргументов эквивалентен вызову git stash push. По умолчанию запись stash отображается как «WIP on <branchname> …​», но при её создании можно указать в командной строке более информативное сообщение.

Последняя созданная вами запись stash хранится в refs/stash; более старые записи находятся в reflog этой ссылки, и на них можно ссылаться с помощью обычного синтаксиса reflog (например, stash@{0} — это самая новая запись stash, stash@{1} — предыдущая, также допустима запись stash@{2.hours.ago}). На записи stash также можно ссылаться, указав только индекс записи (например, целое число <n> эквивалентно stash@{<n>}).

Команды

push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-u | --include-untracked] [ -a | --all] [-q | --quiet] [(-m|--message) <message>] [--pathspec-from-file=<file> [--pathspec-file-nul]] [--] [<pathspec>...]

Сохранить локальные изменения в новой записи stash entry и отменить их, вернув состояние к HEAD (в рабочем дереве и индексе). Часть <message> необязательна и задаёт описание сохранённого состояния.

Чтобы быстро создать снимок, можно опустить «push». В этом режиме элементы pathspec разрешены только после двойного дефиса --, чтобы опечатка в подкоманде не привела к созданию нежелательной записи stash.

save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-u | --include-untracked] [-a | --all] [-q | --quiet] [<message>]

Этот параметр устарел; вместо него следует использовать git stash push. От команды «stash push» он отличается тем, что не принимает pathspec. Вместо этого все аргументы, не являющиеся параметрами, объединяются в сообщение stash.

list [<log-options>]

Вывести список имеющихся записей stash. Для каждой записи stash entry указывается её имя (например, stash@{0} — это самая новая запись, stash@{1} — предыдущая и т. д.), имя ветки, активной при создании записи, и краткое описание коммита, на основе которого она создана.

stash@{0}: WIP on submit: 6ebd0e2... Update git-stash documentation
stash@{1}: On master: 9cc0589... Add git-stash

Команда принимает параметры, применимые к команде git log, чтобы управлять содержимым и форматом вывода. См. git-log[1].

show [-u | --include-untracked | --only-untracked] [<diff-options>] [<stash>]

Показать изменения, записанные в stash, в виде diff между сохранённым содержимым и коммитом, существовавшим при создании записи stash. По умолчанию команда выводит diffstat, но принимает любой формат, известный команде git diff (например, git stash show -p stash@{1}, чтобы просмотреть предпоследнюю запись в формате патча). Если <diff-option> не указан, поведение по умолчанию определяется переменными конфигурации stash.showStat и stash.showPatch. Также можно использовать stash.showIncludeUntracked, чтобы задать, включён ли по умолчанию параметр --include-untracked.

pop [--index] [-q | --quiet] [<stash>]

Удалить одну запись stash из списка и применить её поверх текущего состояния рабочего дерева, то есть выполнить обратную операцию по отношению к git stash push. Рабочий каталог должен соответствовать индексу.

Применение состояния может завершиться конфликтами; в этом случае запись не удаляется из списка stash. Необходимо разрешить конфликты вручную, а затем вызвать git stash drop.

apply [--index] [-q | --quiet] [<stash>]

Аналогично pop, но состояние не удаляется из списка stash. В отличие от pop, <stash> может быть любым коммитом, похожим на коммит, созданный командами stash push или stash create.

branch <branchname> [<stash>]

Создать и переключиться на новую ветку с именем <branchname>, начинающуюся с коммита, на котором изначально была создана запись <stash>, и применить изменения, записанные в <stash>, к новому рабочему дереву и индексу. Если это удаётся и <stash> является ссылкой вида stash@{<revision>}, запись <stash> удаляется.

Это полезно, если ветка, в которой была выполнена команда git stash push, достаточно изменилась и команда git stash apply завершается неудачей из-за конфликтов. Поскольку запись stash применяется поверх коммита, на который указывал HEAD в момент выполнения команды git stash, исходное сохранённое состояние восстанавливается без конфликтов.

clear

Удалить все записи stash. Обратите внимание: после этого эти записи могут быть удалены при очистке, и восстановить их может быть невозможно (возможный способ восстановления описан ниже, в разделе EXAMPLES).

drop [-q | --quiet] [<stash>]

Удалить одну запись stash из списка записей stash.

create

Создать запись stash (обычный объект-коммит) и вернуть её имя объекта, не сохраняя его в пространстве имён ссылок. Это предназначено для использования в скриптах. Скорее всего, это не та команда, которая вам нужна; см. описание команды «push» выше.

store

Сохранить указанную запись stash, созданную с помощью git stash create (висячего коммита слияния), в ссылке stash, обновив reflog stash. Это предназначено для использования в скриптах. Скорее всего, это не та команда, которая вам нужна; см. описание команды «push» выше.

export ( --print | --to-ref <ref> ) [<stash>...]

Экспортировать указанные записи stash или все записи, если ни одна не указана, в цепочку коммитов, которую можно передать с помощью обычных механизмов fetch и push, а затем импортировать с помощью подкоманды import.

import <commit>

Импортировать указанные записи stash из указанного коммита, который должен быть создан командой export, и добавить их в список stash. Чтобы заменить существующие записи stash, сначала используйте clear.

Параметры

-a
--all

Этот параметр допустим только для команд push и save.

Все игнорируемые и неотслеживаемые файлы также сохраняются в stash, а затем удаляются с помощью git clean.

-u
--include-untracked
--no-include-untracked

При использовании с командами push и save все неотслеживаемые файлы также сохраняются в stash, а затем удаляются с помощью git clean.

При использовании с командой show неотслеживаемые файлы из записи stash включаются в diff.

--only-untracked

Этот параметр допустим только для команды show.

Включить в diff только неотслеживаемые файлы из записи stash.

--index

Этот параметр допустим только для команд pop и apply.

Попытаться восстановить не только изменения рабочего дерева, но и изменения индекса. Однако это может не удаться при наличии конфликтов (которые сохраняются в индексе, поэтому применить изменения в исходном виде уже невозможно).

--label-ours=<label>
--label-theirs=<label>
--label-base=<label>

Эти параметры допустимы только для команды apply.

Использовать указанные метки в маркерах конфликтов вместо меток по умолчанию "Updated upstream", "Stashed changes" и "Stash base". Параметр --label-base действует только при merge.conflictStyle=diff3.

-k
--keep-index
--no-keep-index

Этот параметр допустим только для команд push и save.

Все изменения, уже добавленные в индекс, остаются без изменений.

-p
--patch

Этот параметр допустим только для команд push и save.

В интерактивном режиме выбрать фрагменты diff между HEAD и рабочим деревом для сохранения в stash. Запись stash формируется так, чтобы состояние её индекса совпадало с состоянием индекса репозитория, а рабочее дерево содержало только изменения, выбранные в интерактивном режиме. Затем выбранные изменения отменяются в рабочем дереве. О том, как работать в режиме --patch, см. раздел «Интерактивный режим» в документации git-add[1].

Параметр --patch подразумевает параметр --keep-index. Чтобы отменить это поведение, можно использовать --no-keep-index.

-U<n>
--unified=<n>

Создать diff с <n> строками контекста. Число строк контекста по умолчанию равно diff.context или 3, если переменная конфигурации не задана. (-U без <n> принимается без предупреждения как синоним -p из-за исторической особенности.)

--inter-hunk-context=<n>

Показать контекст между фрагментами diff длиной до указанного <number> строк, объединяя таким образом близко расположенные фрагменты. По умолчанию используется значение diff.interHunkContext или 0, если параметр конфигурации не задан.

-S
--staged

Этот параметр допустим только для команд push и save.

Сохранить в stash только изменения, добавленные в индекс. Это похоже на обычный вызов git commit, за исключением того, что состояние фиксируется в stash, а не в текущей ветке.

Параметр --patch имеет приоритет над этим параметром.

--pathspec-from-file=<file>

Этот параметр допустим только для команды push.

Pathspec передаётся в <file>, а не как аргументы командной строки. Если <file> имеет значение -, используется стандартный ввод. Элементы pathspec разделяются LF или CR/LF. Элементы pathspec можно заключать в кавычки, как описано для переменной конфигурации core.quotePath (см. git-config[1]). См. также --pathspec-file-nul и глобальный параметр --literal-pathspecs.

--pathspec-file-nul

Этот параметр допустим только для команды push.

Имеет смысл только вместе с --pathspec-from-file. Элементы pathspec разделяются нулевым символом; все остальные символы воспринимаются буквально (включая символы новой строки и кавычки).

-q
--quiet

Этот параметр допустим только для команд apply, drop, pop, push, save и store.

Тихий режим: не выводить сообщения.

--print

Этот параметр допустим только для команды export.

Создать цепочку коммитов, представляющих экспортированные записи stash, не сохраняя её в пространстве имён ссылок, и вывести идентификатор объекта в стандартный вывод. Предназначено для использования в скриптах.

--to-ref

Этот параметр допустим только для команды export.

Создать цепочку коммитов, представляющих экспортированные записи stash, и сохранить её в указанную ссылку.

--

Этот параметр допустим только для команды push.

Отделяет pathspec от параметров, чтобы устранить неоднозначность.

<pathspec>...

Этот параметр допустим только для команды push.

Новая запись stash сохраняет изменённые состояния только для файлов, соответствующих pathspec. Записи индекса и файлы рабочего дерева также возвращаются к состоянию в HEAD только для этих файлов; остальные файлы остаются без изменений.

Подробнее см. статью pathspec в gitglossary[7].

<stash>

Этот параметр допустим только для команд apply, branch, drop, pop, show и export.

Ссылка вида stash@{<revision>}. Если <stash> не указан, предполагается последняя запись stash (то есть stash@{0}).

Обсуждение

Запись stash представлена коммитом, дерево которого фиксирует состояние рабочего каталога, а его первый родитель — это коммит, на который указывал HEAD при создании записи. Дерево второго родителя фиксирует состояние индекса на момент создания записи; этот родитель является дочерним коммитом HEAD. Граф родословной выглядит так:

       .----W
      /    /
-----H----I

где H — коммит HEAD, I — коммит, фиксирующий состояние индекса, а W — коммит, фиксирующий состояние рабочего дерева.

Примеры

Выполнение pull в грязном дереве

Когда вы заняты какой-либо работой, вы узнаёте, что появились изменения в вышестоящем репозитории, которые могут иметь отношение к вашей работе. Если локальные изменения не конфликтуют с изменениями в вышестоящем репозитории, можно просто выполнить git pull и продолжить работу.

Однако иногда локальные изменения конфликтуют с изменениями в вышестоящем репозитории, и команда git pull отказывается перезаписывать ваши изменения. В таком случае можно временно сохранить изменения в stash, выполнить pull, а затем восстановить их, например так:

$ git pull
 ...
file foobar not up to date, cannot merge.
$ git stash
$ git pull
$ git stash pop
Прерванный рабочий процесс

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

# ... hack hack hack ...
$ git switch -c my_wip
$ git commit -a -m "WIP"
$ git switch master
$ edit emergency fix
$ git commit -a -m "Fix in a hurry"
$ git switch my_wip
$ git reset --soft HEAD^
# ... continue hacking ...

Можно упростить описанные выше действия с помощью git stash, например так:

# ... hack hack hack ...
$ git stash
$ edit emergency fix
$ git commit -a -m "Fix in a hurry"
$ git stash pop
# ... continue hacking ...
Проверка частичных коммитов

Можно использовать git stash push --keep-index, если вы хотите разбить изменения в рабочем дереве на два или более коммита и проверить каждое изменение перед фиксацией:

# ... hack hack hack ...
$ git add --patch foo            # add just first part to the index
$ git stash push --keep-index    # save all other changes to the stash
$ edit/build/test first part
$ git commit -m 'First part'     # commit fully tested change
$ git stash pop                  # prepare to work on all other changes
# ... repeat above five steps until one commit remains ...
$ edit/build/test remaining parts
$ git commit foo -m 'Remaining parts'
Сохранение несвязанных изменений на будущее

Если вы заняты масштабными изменениями и обнаружили несвязанную проблему, о которой не хотите забыть, можно внести соответствующие изменения, добавить их в индекс и выполнить git stash push --staged, чтобы сохранить их в stash для дальнейшего использования. Это похоже на фиксацию добавленных в индекс изменений, только коммит окажется в stash, а не в текущей ветке.

# ... hack hack hack ...
$ git add --patch foo           # add unrelated changes to the index
$ git stash push --staged       # save these changes to the stash
# ... hack hack hack, finish current changes ...
$ git commit -m 'Massive'       # commit fully tested changes
$ git switch fixup-branch       # switch to another branch
$ git stash pop                 # to finish work on the saved changes
Восстановление записей stash, ошибочно очищенных или удалённых

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

git fsck --unreachable |
grep commit | cut -d\  -f3 |
xargs git log --merges --no-walk --grep=WIP

Конфигурация

Всё содержимое этой секции ниже данной строки выборочно включено из документации git-config[1]. Оно совпадает с содержимым соответствующего раздела:

stash.index

Если для этого параметра задано значение true, команды git stash apply и git stash pop ведут себя так, как если бы был указан параметр --index. Значение по умолчанию — false.

stash.showIncludeUntracked

Если для этого параметра задано значение true, команда git stash show показывает неотслеживаемые файлы записи stash. Значение по умолчанию — false.

stash.showPatch

Если для этого параметра задано значение true, команда git stash show без параметров показывает запись stash в формате патча. Значение по умолчанию — false.

stash.showStat

Если для этого параметра задано значение true, команда git stash show без параметров показывает diffstat записи stash. Значение по умолчанию — true.

См. также

git-checkout[1], git-commit[1], git-reflog[1], git-reset[1], git-switch[1]

stash

© 2005–2026 Linus Torvalds and others
Licensed under the GNU General Public License version 2.
https://git-scm.com/docs/git-stash

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API