Git спрятать изменения файла

Обновлено: 04.07.2024

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

Примечание

Переход на git stash push

В конце октября 2017 года в списке рассылки Git проходило обширное обсуждение, по итогам которого команда git stash save признана устаревшей в пользу существующей альтернативы git stash push . Основная причина этого заключается в том, что в git stash push есть возможность сохранить выбранные спецификации пути, что не поддерживает git stash save .

Команда git stash save не исчезнет в ближайшее время, поэтому не беспокойтесь о её внезапной пропаже. Но вы можете начать переход на push для использования новой функциональности.

Припрятывание ваших наработок

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

Теперь вы хотите сменить ветку, но пока не хотите фиксировать ваши текущие наработки; поэтому вы припрячете эти изменения. Чтобы припрятать изменение в выделенное для этого специальное хранилище, выполните git stash или git stash push :

Теперь вы можете увидеть, что рабочая копия не содержит изменений:

В данный момент вы можете легко переключать ветки и работать в любой из них; ваши изменения сохранены. Чтобы посмотреть список припрятанных изменений, вы можете использовать git stash list :

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

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

Спрятанные изменения будут применены к вашим файлам, но файлы, которые вы ранее добавляли в индекс, не будут добавлены туда снова. Чтобы это было сделано, вы должны запустить git stash apply с опцией --index , при которой команда попытается восстановить изменения в индексе. Если вы выполните команду таким образом, то полностью восстановите ваше исходное состояние:

Команда apply только пытается восстановить припрятанные наработки – при этом они останутся в хранилище. Чтобы удалить их, вы можете выполнить git stash drop , указав имя удаляемых изменений:

Вы также можете выполнить git stash pop , чтобы применить припрятанные изменения и тут же удалить их из хранилища.

Необычное припрятывание

У припрятанных изменений есть несколько дополнительных вариантов использования, которые также могут быть полезны. Первый – это использование довольно популярной опции --keep-index с командой git stash . Она просит Git не только припрятать то, что вы уже добавили в индекс, но одновременно оставить это в индексе.

Другой распространённый вариант, который вы, возможно, захотите использовать – это припрятать помимо отслеживаемых файлов и неотслеживаемые. По умолчанию git stash будет сохранять только изменённые и проиндексированные отслеживаемые файлы. Если вы укажете опцию --include-untracked или -u , Git также припрячет все неотслеживаемые файлы, которые вы создали. Однако включение этой опции по-прежнему не будет прятать файлы с явным игнорированием; чтобы дополнительно припрятать игнорируемые файлы, используйте --all (или просто -a ).

И наконец, если вы укажете флаг --patch , Git не будет ничего прятать, а вместо этого в интерактивном режиме спросит вас о том, какие из изменений вы хотите припрятать, а какие оставить в вашем рабочем каталоге.

Создание ветки из припрятанных изменений

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

Это удобное сокращение для того, чтобы легко восстановить припрятанные изменения и поработать над ними в новой ветке.

Очистка рабочего каталога

Наконец, у вас может возникнуть желание не спрятать некоторые из изменений или файлов в вашем рабочем каталоге, а просто избавиться от них. Команда git clean сделает это для вас.

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

С этой командой вы должны быть очень аккуратны, так как она предназначена для удаления неотслеживаемых файлов из вашего рабочего каталога. Даже если вы передумаете, очень часто нельзя восстановить содержимое таких файлов. Более безопасным вариантом является использование команды git stash --all для удаления всего, но с сохранением этого в виде припрятанных изменений.

Предположим, вы хотите удалить мусор и очистить ваш рабочий каталог; вы можете сделать это с помощью git clean . Для удаления всех неотслеживаемых файлов в вашем рабочем каталоге, вы можете выполнить команду git clean -f -d , которая удалит все файлы, а также все каталоги, которые в результате станут пустыми. Параметр -f (сокращение от слова force – заставить) означает принудительное удаление, подчеркивая, что вы действительно хотите это сделать, и требуется, если переменная конфигурации Git clean.requireForce явным образом не установлена в false .

Если вы хотите только посмотреть, что будет сделано, вы можете запустить эту команду с опцией -n , которая означает «имитируй работу команды и скажи мне, что ты будешь удалять».

По умолчанию команда git clean будет удалять только неотслеживаемые файлы, которые не добавлены в список игнорируемых. Любой файл, который соответствует шаблону в вашем .gitignore , или другие игнорируемые файлы не будут удалены. Если вы хотите удалить и эти файлы (например, удалить все файлы .o , генерируемые в процессе сборки, и, таким образом, полностью очистить сборку), вы можете передать команде очистки опцию -x .

Если вы не знаете, что сделает при запуске команда git clean , всегда сначала выполняйте её с опцией -n , чтобы проверить дважды, перед заменой -n на -f и выполнением настоящей очистки. Другой способ, который позволяет вам более тщательно контролировать сам процесс – это выполнение команды с опцией -i (в «интерактивном» режиме).

Ниже показано выполнение команды очистки в интерактивном режиме.

Таким образом, вы можете просмотреть каждый файл отдельно или указать шаблоны для удаления в интерактивном режиме.

Примечание

Есть шанс возникновения странной ситуации, когда вам, возможно, придется проявить особую настойчивость, прося Git очистить ваш рабочий каталог. Если вы оказались в рабочем каталоге, в который вы скопировали или клонировали другие репозитории Git (возможно, в виде подмодулей), даже git clean -fd откажется удалить эти каталоги. В таких случаях для проявления упорства вам нужно добавить второй параметр -f .

Команда 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 выводит список всех ваших прятаний:

git stash list

Самые старые «прятанья» отображаются внизу списка, самые свежие сверху. Каждое прятанье имеет идентификатор с номером, например, stash@

Git stash apply

Команда git stash apply берет самое свежее прятанье ( stash@ ) и применяет его к репозиторию. То есть изменения, которые находятся в этом прятанье, применяются к текущему репозиторию. Это похоже на то, как вы применяете патч, только в качестве патча выступает ваше прятанье.

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

Git stash pop

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

Было:

Стало после git stash pop:

Также можно указать идентификатор прятанья:

Git stash show

Команда git stash show показывает, какие изменения содержатся в прятанье.

git stash show

Показываются изменения в файлах для самого последнего прятанья (для stash@ ):

Чтобы показать полный diff, то есть увидеть сами изменения, используется ключ -p :

Можно указать идентификатор прятанья, чтобы вывести изменения в нем:

Git stash branch

Команда git stash branch создает новую ветку с последним прятаньем, и затем удаляет последнее прятанье (как git stash pop).

Можно также указать идентификатор прятанья:

Git stash drop

Команда git stash drop удаляет самое последнее прятанье (stash@).

Можно указать идентификатор прятанья, которое нужно удалить:

Git stash clear

Команда git stash clear удаляет все прятанья. Будьте внимательные перед тем, как ее выполнять, чтобы не удалить нужные данные.

Мы рассмотрели возможные варианты использования команды git stash . Это очень полезный инструмент при работе с Git.

Команда 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 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@ : при этом вы ссылаетесь на n-ю запись в журнале ссылок stash . Поскольку набор отложенных изменений представляет собой обычный коммит, его можно просмотреть с помощью команды git log :

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

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

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

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

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

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

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

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

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

    Обновление 17 Мая 2018:

    новые версии git теперь имеют git stash --all который прячет все файлы, включая неотслеженные и игнорируемые файлы.
    git stash --include-untracked больше не касается игнорируемых файлов (проверено на git 2.16.2).

    оригинальный ответ ниже:

    внимание, это приведет к необратимому удалению ваших файлов, если у вас есть какие-либо записи каталога/* в вашем файле gitignore.

    для версии 1.7.7 вы можете использовать git stash --include-untracked или git stash save -u чтобы спрятать неотслеженные файлы без их размещения.

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

    начиная с git 1.7.7, git stash принимает --include-untracked опция (или короткая рука -u ). Включить неотслеживаемый файлы в свой тайник, используйте одну из следующих команд:

    внимание, это приведет к необратимому удалению ваших файлов, если у вас есть какие-либо записи каталога/* в вашем файле gitignore.

    Добавить файл в индекс:

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

    как уже было сказано в другом месте, ответ git add файл. например:

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

    это не удастся, как показано ниже:

    Итак, что вы можете сделать? Ну, вы должны действительно добавить файл , вы можете эффективно удалить его позже, с git rm --cached :

    и тогда вы можете продолжать работать, в том же состоянии, в котором вы были до git add (именно с неотслеживаемый файл называется path/to/untracked-file ; плюс любые другие изменения, которые вы, возможно, должны были отслеживать файлы).

    еще одна возможность для рабочего процесса на этом будет что-то вроде:

    [Примечание: как уже упоминалось в комментарии @mancocapac, вы можете добавить --exclude-standard к (так, git ls-files -o --exclude-standard ).]

    . который также может быть легко написан-даже псевдонимы будут делать (представлены в синтаксисе zsh; отрегулируйте по мере необходимости) [кроме того, я сократил имя файла, чтобы все это поместилось на экране без прокрутки в этом ответе; не стесняйтесь заменять альтернативное имя файла по вашему выбору]:

    обратите внимание, что последний может быть лучше в качестве сценария оболочки или функции, чтобы разрешить параметры для git stash , в случае, если вы не хочу!--15--> но apply , и/или хотите иметь возможность указать конкретный тайник, а не просто взять верхний. Возможно, это (вместо второго псевдонима, выше) [пробелы разделены, чтобы соответствовать без прокрутки; повторно добавить для повышения разборчивости]:

    Примечание: в этой форме вам нужно указать аргумент действия, а также идентификатор, если вы собираетесь предоставить идентификатор тайника, например unstashall apply stash@ или unstashall pop stash@

    что конечно, вы бы положили в свой .zshrc или эквивалент для того чтобы сделать существует долгосрочность.

    надеюсь, этот ответ кому-то полезен, собирая все вместе в одном ответе.

    на Git версии 2.8.1: следующие работы для меня.

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

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

    вы можете использовать либо pop и применить позже следующим образом.

    я смог спрятать просто неотслеженные файлы, выполнив:

    последний выскакивает тайник отслеживаемых файлов, таким образом оставляя только неотслеживаемые файлы.

    Я думал, что это можно решить, сообщив git, что файл существует, а не фиксировать все его содержимое в промежуточной области, а затем вызвать git stash . Аракнид описание как сделать бывших.

    или

    однако последнее не работает:

    Вы можете просто сделать это с помощью ниже команду

    или

    подробнее о git stash посетите этот пост (нажмите здесь)

    Я имел обыкновение размышлять и желать ту же самую функцию. Но со временем я заметил, что это действительно не нужно. Когда вы прячете, это нормально, чтобы оставить новые файлы. Ничего "плохого" с ними не может случиться (когда вы проверяете что-то еще, git будет ошибаться и не перезаписывать существующий неотслеженный файл)

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

    Читайте также: