Команда 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 @@
+<link rel="stylesheet" href="style.css"/>

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

При желании можно отложить один файл, несколько файлов или отдельные изменения в файлах. Если передать команде 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 @@
+<link rel="stylesheet" href="style.css"/>
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 шифрует рабочий каталог и раздел проиндексированных файлов в виде коммитов:

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

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

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

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

    git stash --all

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

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

Ознакомьтесь с этим интерактивным обучающим руководством.

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