- Команда Git stash. Как прятать изменения в Git
- Для чего нужен git stash
- Git stash
- Git stash save
- Git stash list
- Git stash apply
- Git stash pop
- Git stash show
- Git stash branch
- Git stash drop
- Git stash clear
- git stash
- Откладывание кода
- Применение отложенных изменений
- Откладывание неотслеживаемых или игнорируемых файлов
- Управление несколькими наборами отложенных изменений
- Просмотр различий между наборами отложенных изменений
- Частичное откладывание изменений
- Создание ветки из отложенных изменений
- Удаление отложенных изменений
- Принцип работы команды git stash
- Почему git stash pop говорит, что не может восстановить неотслеживаемые файлы из записи в тайнике?
- Что внутри тайника
- Восстановление тайника
Команда Git stash. Как прятать изменения в Git
Команда git stash предназначена для того, чтобы поместить текущие изменения, которые вы выполнили в файлах, в отдельное хранилище, и вернуть файлы к исходному состоянию. То есть git stash прячет изменения в файлах и сохраняет эти изменения отдельно, чтобы потом можно было их вернуть.
Для чего нужен git stash
Приведем пример. Например, вы выполнили какие-нибудь изменения в файлах и хотите переключиться на другую ветку, но чтобы там не было ваших текущих изменений. С помощью команды git stash можно спрятать эти изменения. Ваши изменения помещаются в отдельное хранилище — в стек, а вы можете спокойно переключиться на другую ветку.
Всё, что вы прячете с помощью git stash, попадает в отдельный список. Затем вы можете извлекать оттуда то, что вы туда спрятали — ваши «прятанья» (далее по тексту будет использоваться это слово).
Рассмотрим, как пользоваться командой git stash
Git stash
Чтобы спрятать изменения достаточно выполнить команду:
Git stash save
Команда git stash save выполняет то же самое, что и git stash , но имеет несколько полезных опций.
Например, можно сохранить изменения и добавить сообщение — подписать изменения, чтобы потом вспомнить, что именно было спрятано. В качестве сообщения, например, можно написать о том, какие именно изменения выполнены в файлах.
Git stash не прячет файлы, которые не добавлены в репозиторий. Чтобы их спрятать с остальными изменениями используется опция —include-untracked (или -u ):
Git stash list
Каждое выполнение git stash или git stash save на самом деле создает отдельный коммит и сохраняет его отдельно (в стек).
Команда git stash list выводит список всех ваших прятаний:
Самые старые «прятанья» отображаются внизу списка, самые свежие сверху. Каждое прятанье имеет идентификатор с номером, например, stash@ <0>
Git stash apply
Команда git stash apply берет самое свежее прятанье ( stash@ <0>) и применяет его к репозиторию. То есть изменения, которые находятся в этом прятанье, применяются к текущему репозиторию. Это похоже на то, как вы применяете патч, только в качестве патча выступает ваше прятанье.
Если вы хотите применить какое-нибудь конкретное прятанье, можно указать его идентификатор:
Git stash pop
Команда git stash pop выполняет все тоже самое, что и команда git stash apply , но удаляет прятанье, которое она применяет к репозиторию.
Было:
Стало после git stash pop:
Также можно указать идентификатор прятанья:
Git stash show
Команда git stash show показывает, какие изменения содержатся в прятанье.
Показываются изменения в файлах для самого последнего прятанья (для stash@ <0>):
Чтобы показать полный diff, то есть увидеть сами изменения, используется ключ -p :
Можно указать идентификатор прятанья, чтобы вывести изменения в нем:
Git stash branch
Команда git stash branch создает новую ветку с последним прятаньем, и затем удаляет последнее прятанье (как git stash pop).
Можно также указать идентификатор прятанья:
Git stash drop
Команда git stash drop удаляет самое последнее прятанье (stash@<0>).
Можно указать идентификатор прятанья, которое нужно удалить:
Git stash clear
Команда git stash clear удаляет все прятанья. Будьте внимательные перед тем, как ее выполнять, чтобы не удалить нужные данные.
Мы рассмотрели возможные варианты использования команды git stash . Это очень полезный инструмент при работе с Git.
Источник
git stash
Команда git stash позволяет на время «сдать в архив» (или отложить) изменения, сделанные в рабочей копии, чтобы вы могли применить их позже. Откладывание изменений полезно, если вам необходимо переключить контекст и вы пока не готовы к созданию коммита.
Откладывание кода
Команда git stash сохраняет неподтвержденные изменения (индексированные и неиндексированные) в отдельном хранилище, чтобы вы могли вернуться к ним позже. Затем происходит откат до исходной рабочей копии. Например:
Теперь вы можете вносить изменения, создавать новые коммиты, переключаться между ветками и выполнять другие операции Git. По необходимости отложенные изменения можно будет применить позже.
Отложенные изменения сохраняются в локальном репозитории Git и не передаются на сервер при выполнении команды push.
Применение отложенных изменений
Чтобы применить ранее отложенные изменения, воспользуйтесь командой git stash pop :
При извлечении отложенных изменений они удаляются из набора и применяются к рабочей копии.
Вы также можете применить изменения к рабочей копии, не удаляя их из набора отложенных изменений. Для этого воспользуйтесь командой git stash apply :
Это полезно, если вам нужно применить одни и те же отложенные изменения к нескольким веткам.
Теперь вы умеете выполнять основные операции с отложенными изменениями. Однако необходимо помнить о следующей особенности команды git stash : по умолчанию Git не создает отложенные изменения для неотслеживаемых или игнорируемых файлов.
Откладывание неотслеживаемых или игнорируемых файлов
По умолчанию команда git stash создает следующие отложенные изменения:
- изменения, добавленные в раздел проиндексированных файлов (индексированные изменения);
- изменения в файлах, отслеживаемых Git в настоящее время (неиндексированные изменения).
При этом следующие файлы отложены не будут:
- новые файлы в рабочей копии, которые еще не были проиндексированы;
- игнорируемые файлы.
Поэтому если в приведенный выше пример добавить третий файл — неиндексированный (т. е. без выполнения команды git add ), при выполнении команды git stash этот файл не будет отложен.
Запуск git stash с параметром -u (или —include-untracked ) позволяет отложить неотслеживаемые файлы:
Можно также отложить изменения, внесенные в игнорируемые файлы. Для этого используйте параметр -a (или —all ) при запуске команды git stash .
Управление несколькими наборами отложенных изменений
Вы можете создать несколько наборов отложенных изменений. Команду git stash можно выполнить несколько раз, после чего можно будет просмотреть список созданных наборов с помощью команды git stash list . По умолчанию отложенные изменения имеют пометку WIP (незавершенная работа) наверху ветки или коммита, в которых они были отложены. Возможно, со временем вам будет трудно вспомнить содержимое каждого набора:
Рекомендуем добавлять к отложенным изменениям описание в качестве подсказки. Для этого используется команда git stash save «сообщение» :
По умолчанию команда git stash pop применяет последний набор отложенных изменений: stash@
Если вам нужно применить определенный набор ранее отложенных изменений, укажите его идентификатор в качестве последнего аргумента. Это можно сделать так:
Просмотр различий между наборами отложенных изменений
Выполните команду git stash show , чтобы просмотреть сводные данные по набору отложенных изменений:
Или укажите параметр -p (или —patch ), чтобы просмотреть разницу между наборами изменений:
Частичное откладывание изменений
При желании можно отложить один файл, несколько файлов или отдельные изменения в файлах. Если передать команде git stash параметр -p (или —patch ), она будет выполняться для каждого измененного участка кода в рабочей копии, запрашивая подтверждение на откладывание:
Нажмите ?, чтобы увидеть полный список команд для работы с участками кода. Часто используются следующие команды:
Команда | Описание |
---|---|
/ | искать участок кода по регулярному выражению |
? | Справка |
n | не откладывать участок кода |
q | выйти (все выбранные участки будут отложены) |
s | разделить участок кода на меньшие части |
y | отложить участок кода |
Специальной команды для прерывания не предусмотрено, но прекратить процесс откладывания можно, нажав CTRL-C (сигнал SIGINT).
Создание ветки из отложенных изменений
Если изменения в ветке отличаются от отложенных изменений, операции извлечения или применения последних могут привести к конфликтам. Вместо этого вы можете создать новую ветку с помощью команды git stash branch и применить отложенные изменения к ней. Это можно сделать так:
Новая ветка создается на основе коммита, изменения в котором использовались при создании набора. Затем к этой ветке применяются извлеченные изменения.
Удаление отложенных изменений
Удалить определенный набор отложенных изменений можно с помощью команды git stash drop :
Следующая команда удаляет все наборы отложенных изменений:
Принцип работы команды git stash
Если вы просто хотели получить информацию о том, как использовать команду git stash , то дальше читать необязательно. Однако если вам необходимо узнать о принципах работы Git (и git stash ) — продолжайте чтение!
Наборы отложенных изменений шифруются в репозитории в виде коммитов. Специальная ссылка в .git/refs/stash указывает на последний созданный набор отложенных изменений, а для ранее созданных наборов изменений используются ссылки из журнала ссылок stash . Именно поэтому для просмотра наборов отложенных изменений используется ссылка stash@
В зависимости от отложенных элементов выполнение команды 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 .
Параметр —include-untracked позволяет также зашифровать все изменения неотслеживаемых файлов в виде дополнительного коммита.
Параметр —all позволяет включить изменения игнорируемых файлов в один коммит с изменениями неотслеживаемых файлов.
При выполнении команды git stash pop изменения из описанных выше коммитов применяются к рабочей копии и разделу проиндексированных файлов, извлеченный коммит удаляется из журнала ссылок на отложенные изменения, и ссылки в журнале сдвигаются. Извлеченные коммиты не удаляются сразу, но помечаются к удалению в будущем при сборе мусора.
Готовы изучить Git?
Ознакомьтесь с этим интерактивным обучающим руководством.
Источник
Почему git stash pop говорит, что не может восстановить неотслеживаемые файлы из записи в тайнике?
У меня была куча поэтапных и неустановленных изменений, и я хотел быстро переключиться на другую ветку, а затем вернуться обратно.
Поэтому я внес свои изменения, используя:
(Оглядываясь назад, я, наверное, мог бы использовать —include-untracked вместо —all )
Затем, когда я пошел, чтобы открыть тайник, я получил много ошибок в следующих строках:
Похоже, что никаких изменений из тайника не восстановлено.
Я тоже пробовал, $ git stash branch temp но показывает те же ошибки.
Я нашел способ обойти это, которое нужно было использовать:
Катастрофа пока предотвращена, но это вызывает некоторые вопросы.
Почему вообще возникла эта ошибка и как избежать ее в следующий раз?
В качестве небольшого дополнительного объяснения обратите внимание, что git stash выполняется либо две, либо три фиксации. По умолчанию два; вы получите три, если используете любое написание —all или —include-untracked .
Эти два, или три, совершающие специальные в одном важном пути: они находятся на нет отрасли. Git находит их по специальному имени stash . 1 Однако самое важное — это то, что Git позволяет — и заставляет — делать с этими двумя или тремя коммитами. Чтобы понять это, нам нужно посмотреть, что находится в этих коммитах.
Что внутри тайника
Каждая фиксация может содержать одну или несколько родительских коммитов. Они образуют график, где более поздние фиксации указывают на более ранние. Тайник обычно содержит две фиксации, которые я люблю вызывать i для содержимого индексной / промежуточной области и w для содержимого рабочего дерева. Помните также, что каждый коммит содержит снимок. При обычной фиксации этот снимок создается из содержимого области индекса / промежуточной области. Таким образом, i фиксация на самом деле является совершенно нормальной фиксацией! Его просто нет ни в одной ветке:
Если вы создаете обычный тайник, git stash код w теперь копирует все ваши отслеживаемые файлы рабочего дерева (во временный вспомогательный индекс). Git устанавливает, что первый родительский элемент этой w фиксации указывает на HEAD фиксацию, а второй родительский элемент указывает на фиксацию i . Наконец, он stash указывает на этот w коммит:
Если вы добавите —include-untracked или —all , Git сделает дополнительную фиксацию, u между созданием i и w . Содержимое моментального снимка u — это файлы, которые не отслеживаются, но не игнорируются ( —include-untracked ), или файлы, которые не отслеживаются, даже если они игнорируются ( —all ). Это дополнительное u обязательство не имеют нет родителей, а затем , когда git stash марка w , она устанавливает w «s третьего родителя это u совершить, так что вы получите:
Git также, на этом этапе, удаляет все файлы рабочего дерева, которые были завершены в u фиксации (используя git clean для этого).
Восстановление тайника
Когда вы собираетесь восстановить тайник, у вас есть возможность использовать —index или не использовать его. Это говорит git stash apply (или какой — либо из команд , которые внутренне использовать apply , например pop ) , что он должен использовать i совершить , чтобы попытаться изменить свой текущий индекс. Эта модификация выполняется с помощью:
(более или менее; здесь есть куча мельчайших деталей, которые мешают базовой идее).
Если вы опустите —index , git stash apply полностью игнорирует i фиксацию.
Если в тайнике есть только две фиксации, git stash apply теперь можно применить w фиксацию. Он делает это, вызывая git merge 2 (не позволяя ему фиксировать или обрабатывать результат как обычное слияние), используя исходный коммит, на котором был создан тайник ( i родительский элемент и w первый родительский элемент) в качестве базы слияния, w как —theirs commit, а ваш текущий (HEAD) коммит в качестве цели слияния. Если слияние прошло успешно, все в порядке — ну, по крайней мере, Git так думает — и git stash apply само успешно. Если раньше вы применяли git stash pop тайник, код теперь отбрасывает тайник. 3 Если слияние не удалось, Git объявляет, что применение не удалось. Если вы использовали git stash pop , код сохраняет тайник и выдает то же состояние отказа, что и для git stash apply .
Но если у вас есть третья фиксация — если u в тайнике, который вы применяете, есть фиксация — тогда все меняется! Невозможно сделать вид, что u фиксации не существует. 4 Git настаивает на извлечении всех файлов из этого u коммита в текущее дерево работы. Это означает, что файлы должны либо не существовать вовсе, либо иметь то же содержимое, что и в u фиксации.
Для этого вы можете использовать git clean себя, но помните, что неотслеживаемые файлы (игнорируемые или нет) больше не существуют в репозитории Git, поэтому убедитесь, что все эти файлы могут быть уничтожены! Или вы можете создать временный каталог и переместить туда файлы для безопасного хранения — или даже сделать другой git stash save -u или git stash save -a , поскольку они будут работать git clean за вас. Но это просто оставляет вам u тайник в другом стиле, с которым вы будете разбираться позже.
+1 Это на самом деле refs/stash . Это имеет значение, если вы создаете ветку с именем stash : полное имя ветки refs/heads/stash , поэтому они не конфликтуют. Но не делайте этого: Git не будет возражать, но вы запутаетесь. 🙂
2 git stash код на самом деле использует git merge-recursive прямо здесь. Это необходимо по нескольким причинам, а также имеет побочный эффект, заключающийся в том, что Git не рассматривает это как слияние при разрешении конфликтов и фиксации.
3 Вот почему я рекомендую избегать git stash pop в пользу git stash apply . Вы получаете шанс рассмотреть то , что получил применены, и решить , был ли он на самом деле применяется правильно. В противном случае у вас все еще есть тайник, а это значит, что вы можете использовать его, git stash branch чтобы полностью восстановить все. Ну, при условии отсутствия этой надоедливой u фиксации.
+4 Там действительно должно быть: git stash apply —skip-untracked что ли. Также должен быть вариант, который означает перетаскивание всех этих u файлов фиксации в новый каталог , например git stash apply —untracked-into , возможно.
Источник