Команда git stash позволяет на время архивировать (или «отложить») изменения, сделанные в рабочей копии, чтобы вы могли применить их позже. Откладывание изменений полезно, если вам необходимо переключить контекст и вы пока не готовы к созданию коммита.

Откладывание кода

Команда git stash сохраняет незафиксированные изменения (подготовленные и неподготовленные) в отдельном хранилище, чтобы вы могли вернуться к ним позже. Затем происходит откат до исходной рабочей копии. Например:

$ git status On branch master Changes to be committed: new file: style.css Changes not staged for commit: modified: index.html $ git stash Saved working directory and index state WIP on master: 5002d47 our new homepage HEAD is now at 5002d47 our new homepage $ git status On branch master nothing to commit, working tree clean

Теперь вы можете вносить изменения, создавать новые коммиты, переключаться между ветками и выполнять другие операции Git. По необходимости отложенные изменения можно будет применить позже.

Отложенные изменения сохраняются в локальном репозитории Git и не передаются на сервер при выполнении команды push.

Применение отложенных изменений

Чтобы применить ранее отложенные изменения, воспользуйтесь командой git stash pop:

$ git status On branch master nothing to commit, working tree clean $ git stash pop On branch master Changes to be committed: new file: style.css Changes not staged for commit: modified: index.html Dropped refs/stash@{0} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)

При извлечении отложенных изменений они удаляются из набора и применяются к рабочей копии.

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

$ git stash apply On branch master Changes to be committed: new file: style.css Changes not staged for commit: modified: index.html

Это полезно, если вам нужно применить одни и те же отложенные изменения к нескольким веткам.

Теперь вы умеете выполнять основные операции с отложенными изменениями. Однако необходимо помнить о следующей особенности командыgit stash: по умолчанию Git не накапливает изменения в неотслеживаемых или игнорируемых файлах.

Откладывание неотслеживаемых или игнорируемых файлов

По умолчанию команда git stash накапливает следующее:

  • изменения, добавленные в индекс (подготовленные изменения);
  • изменения в файлах, отслеживаемых Git в настоящее время (неподготовленные изменения)
  • .

При этом следующие файлы отложены не будут:

  • новые файлы в рабочей копии, которые еще не были подготовлены;
  • игнорируемые файлы.

Поэтому если в пример выше добавить третий файл без его подготовки (т. е. без выполнения команды git add), при выполнении команды git stash этот файл не будет отложен.

$ script.js $ git status On branch master Changes to be committed: new file: style.css Changes not staged for commit: modified: index.html Untracked files: script.js $ git stash Saved working directory and index state WIP on master: 5002d47 our new homepage HEAD is now at 5002d47 our new homepage $ git status On branch master Untracked files: script.js

Запуск git stash с опцией -u (или --include-untracked) позволит отложить неотслеживаемые файлы:

$ git status On branch master Changes to be committed: new file: style.css Changes not staged for commit: modified: index.html Untracked files: script.js $ git stash -u Saved working directory and index state WIP on master: 5002d47 our new homepage HEAD is now at 5002d47 our new homepage $ git status On branch master nothing to commit, working tree clean

Изменения также можно вносить в игнорируемые файлы. Для этого используйте опцию -a (или --all) при запуске команды git stash.

Опции команды git stash

Управление несколькими наборами отложенных изменений

Вы можете создать несколько наборов отложенных изменений. Команду git stash можно выполнить несколько раз, после чего у вас будет возможность просмотреть список наборов с помощью команды git stash list. По умолчанию отложенные изменения имеют пометку WIP (в процессе работы) наверху ветки или коммита, в которых они были отложены. Возможно, со временем вам будет трудно вспомнить содержимое каждого набора:

$ git stash list stash@{0}: WIP on master: 5002d47 our new homepage stash@{1}: WIP on master: 5002d47 our new homepage stash@{2}: WIP on master: 5002d47 our new homepage

Рекомендуем добавлять к отложенным изменениям описание в качестве подсказки. Для этого используется команда git stash save "сообщение":

$ git stash save "add style to our site" Saved working directory and index state On master: add style to our site HEAD is now at 5002d47 our new homepage $ git stash list stash@{0}: On master: add style to our site stash@{1}: WIP on master: 5002d47 our new homepage stash@{2}: WIP on master: 5002d47 our new homepage

По умолчанию команда git stash pop применяет последний набор отложенных изменений: stash@{0}

Если вам нужно применить определенный набор ранее отложенных изменений, укажите его идентификатор в качестве последнего аргумента. Это можно сделать так:

$ git stash pop stash@{2}

Просмотр различий между наборами отложенных изменений

Выполните команду git stash show, чтобы просмотреть сводные данные по набору отложенных изменений:

$ git stash show index.html | 1 + style.css | 3 +++ 2 files changed, 4 insertions(+)

Или укажите опцию -p (или --patch), чтобы просмотреть разницу между наборами изменений:

$ git stash show -p diff --git a/style.css b/style.css new file mode 100644 index 0000000..d92368b --- /dev/null +++ b/style.css @@ -0,0 +1,3 @@ +* { + text-decoration: blink; +} diff --git a/index.html b/index.html index 9daeafb..ebdcbd2 100644 --- a/index.html +++ b/index.html @@ -1 +1,2 @@ +

Частичное откладывание изменений

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

$ git stash -p diff --git a/style.css b/style.css new file mode 100644 index 0000000..d92368b --- /dev/null +++ b/style.css @@ -0,0 +1,3 @@ +* { + text-decoration: blink; +} Stash this hunk [y,n,q,a,d,/,e,?]? y diff --git a/index.html b/index.html index 9daeafb..ebdcbd2 100644 --- a/index.html +++ b/index.html @@ -1 +1,2 @@ + Stash this hunk [y,n,q,a,d,/,e,?]? n
git stash -p

Нажмите ?, чтобы увидеть полный список команд для работы над участками кода. Часто используются следующие команды:

Команда Описание
/ искать участок кода по регулярному выражению
? справка
n не откладывать участок кода
q выйти (все выбранные участки будут отложены)
s разделить участок кода на меньшие части
y отложить участок кода

Специальной команды для отмены не предусмотрено, но отменить процесс откладывания можно, нажав CTRL-C (сигнал SIGINT).

Создание ветки из отложенных изменений

Если изменения в ветке отличаются от отложенных, операции извлечения или применения последних могут привести к конфликтам. Вместо этого вы можете создать новую ветку с помощью команды git stash branch и применить отложенные изменения к ней. Это можно сделать так:

 $ git stash branch add-stylesheet stash@{1} Switched to a new branch 'add-stylesheet' On branch add-stylesheet Changes to be committed: new file: style.css Changes not staged for commit: modified: index.html Dropped refs/stash@{1} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)

Новая ветка создается на основе коммита, изменения в котором использовались при создании набора. Затем к этой ветке применяются извлеченные изменения.

Удаление отложенных изменений

Удалить определенный набор отложенных изменений можно с помощью команды git stash drop:

$ git stash drop stash@{1} Dropped stash@{1} (17e2697fd8251df6163117cb3d58c1f62a5e7cdb)

Следующая команда удаляет все наборы отложенных изменений:

$ git stash clear

Принцип работы команды git stash

Если вы хотели получить сведения о том, как использовать команду git stash, то дальше читать необязательно. Однако если вам необходимо узнать о принципах работы Git (и git stash) — продолжайте чтение!

Наборы отложенных изменений шифруются в репозитории в виде коммитов. Специальная ссылка .git/refs/stash указывает на последний созданный набор отложенных изменений, а для ранее созданных наборов изменений используются ссылки stash из журнала ссылок. Именно поэтому для просмотра наборов отложенных изменений используется ссылка stash@{n}. Эта команда выводит конкретную n-ную запись из каталога stash в журнале ссылок. Поскольку набор отложенных изменений представляет собой обычный коммит, просмотреть его можно с помощью команды git log:

$ git log --oneline --graph stash@{0} *-. 953ddde WIP on master: 5002d47 our new homepage |\ \ | | * 24b35a1 untracked files on master: 5002d47 our new homepage | * 7023dd4 index on master: 5002d47 our new homepage |/ * 5002d47 our new homepage

В зависимости от отложенных элементов выполнение команды git stash создаст два или три новых коммита. На схеме выше создаются следующие коммиты:

  • stash@{0} — новый коммит для хранения отслеживаемых файлов, которые находились в рабочей копии при запуске команды git stash;
  • первый родитель stash@{0} — существующий коммит, который при запуске команды git stash находился в ветке, на которую указывал HEAD;
  • второй родитель stash@{0} — новый коммит, выступавший в роли индекса при запуске команды git stash;
  • третий родитель stash@{0} — новый коммит, представляющий неотслеживаемые файлы, которые находились в рабочей копии при запуске команды git stash. Третий родитель создается, только если:
    • рабочая копия действительно содержит неотслеживаемые файлы, и
    • вы назначили опцию --include-untracked или --all команде git stash.

Ниже показано, как команда git stash шифрует рабочий каталог и индекс в виде коммитов:

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

    Before stashing
  • При выполнении команды git stash все изменения отслеживаемых файлов шифруются в виде двух новых коммитов в ориентированном ациклическом графе. При этом один коммит используется для неподготовленных изменений, а другой — для изменений, подготовленных в индексе. Для указания на них используется специальная ссылка refs/stash.

    Git stash
  • Опция --include-untracked также позволяет шифровать все изменения неотслеживаемых файлов в виде дополнительного коммита.

    Git stash --include-untracked
  • Опция --all позволяет включить изменения игнорируемых файлов в тот же коммит, который содержит изменения неотслеживаемых файлов.

    Git Stash --all

При выполнении команды git stash pop изменения из коммитов выше применяются к рабочей копии и индексу, тогда как извлеченный коммит удаляется из журнала ссылок на отложенные изменения (при этом порядок ссылок в нем меняется). Извлеченные коммиты не удаляются сразу, но помечаются к удалению в будущем.

Готовы изучить Git?

Попробуйте это интерактивное учебное руководство.

Начните прямо сейчас