Как распаковать только определенные файлы?

388

Я спрятал свои изменения. Теперь я хочу распаковать только некоторые файлы из тайника. Как я могу это сделать?

Морфей
источник
4
Я думаю, что вы должны применить весь тайник, но тогда вы можете выборочно повторно копить.
Ричард
4
@AbdouTahiri Что не так с тайником?
Алекс
32
@AbdouTahiri Uhhhh .. git stash является законной функцией и чрезвычайно полезной. Я использую это ежедневно. Скажем, коллеге нужно, чтобы я что-то просмотрел, но я нахожусь в середине сложного набора изменений. Я не собираюсь фиксировать кучу сломанного кода, просто чтобы сменить ветку. Я собираюсь прятаться, переключать ветки, просматривать, переключаться обратно, распаковывать. Вы хотите уточнить, кто или почему git stash якобы «не рекомендуется»? То, что твоя история с паршивцами запутана и трудна для чтения, еще не значит, что все остальные. Грязный набор для git - просто плохой рабочий процесс, а не недостаток Git.
dudewad
6
@alex Ничего. С git stash все в порядке. Продолжайте использовать это.
dudewad

Ответы:

463

Как упоминалось ниже и подробно описано в разделе « Как извлечь отдельный файл (или изменения в файл) из git stash? », Вы можете применить команду use git checkoutили git showдля восстановления определенного файла.

git checkout stash@{0} -- <filename>

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

(Как заметил по Jaime М. , для определенной оболочки , как Tcsh , где вам нужно , чтобы избежать специальных символов, синтаксис будет: git checkout 'stash@{0}' -- <filename>)

или сохранить его под другим именем файла:

git show stash@{0}:<full filename>  >  <newfile>

(обратите внимание, что здесь <full filename>указан полный путь к файлу относительно верхнего каталога проекта (думаю: относительно stash@{0})).

Юсер предлагает в комментариях :

Если вы хотите выбрать вручную, какие изменения вы хотите применить из этого файла:

git difftool stash@{0}..HEAD -- <filename>

Вивек добавляет в комментариях :

Похоже, что " git checkout stash@{0} -- <filename>" восстанавливает версию файла на момент выполнения тайника - он НЕ применяет (только) сохраненные изменения для этого файла.
Чтобы сделать последнее:

git diff stash@{0}^1 stash@{0} -- <filename> | git apply

(как заметил по peterflynn , что вам может понадобиться | git apply -p1в некоторых случаях, удаление одного ( p1) , ведущий слэш от традиционных путей дифф)


Как прокомментировал: "unstash" ( git stash pop), то:

  • добавить то, что вы хотите сохранить в индексе ( git add)
  • спрятать остальное: git stash --keep-index

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

VonC
источник
5
Это не работает, если вы не можете git stash popиз-за конфликтов файлов. В этом случае ответ Баламуругана А помог мне.
Андрей
1
Если вы хотите вручную выбрать, какие изменения вы хотите применить из этого файла, вы можете использовать git difftool stash @ {0} .. HEAD - <имя файла>
yucer
5
Похоже, "git checkout stash @ {0} - <filename>" восстанавливает версию файла на момент, когда был выполнен stash - он НЕ применяет (только) сохраненные изменения для этого файла. Для этого: «git diff stash @ {0} ^ 1 stash @ {0} - <имя файла> | git apply»
Vivek
1
@JaimeM. Спасибо. Я включил ваш комментарий в ответ для большей наглядности.
VonC
1
Предполагая, что это unstashозначает pop, как мне кажется, в большинстве случаев, вероятно, это лишь частично отвечает на вопрос. Как вы тогда удаляете выборочно примененные части из тайника, чтобы избежать последующих конфликтов и / или путаницы при появлении оставшихся изменений?
DylanYoung
115
git checkout stash@{N} <File(s)/Folder(s) path> 

Например. Чтобы восстановить только файл ./test.c и папку ./include из последнего спрятанного файла,

git checkout stash@{0} ./test.c ./include
Баламуруган А
источник
12
Это правильный ответ! Однострочная команда для применения только спрятанных изменений из определенных файлов, работает как шарм!
уровня
1
Чтобы применить (просто) сохраненные изменения для файла: «git diff stash @ {N} ^ 1 stash @ {N} - <имя файла> | git apply»
Vivek
Это работает и для меня. Просто выборочно извлеките файлы, необходимые для использования из тайника, и все готово. Я застрял в этом я использовал -aфлаг при создании тайника.
Раджив Ранджан
1
@ 4 уровня Я думаю, что «применить скрытые изменения» не то, что происходит, верно? Я думаю, что "перезаписать все, что у вас есть с копией из тайника", это то, что происходит.
MSN
35

Я думаю, что ответ VonC, вероятно, то, что вы хотите, но вот способ сделать выборочное «git apply»:

git show stash@{0}:MyFile.txt > MyFile.txt
Майк Монкевич
источник
4
В некоторых случаях это может быть тем, что вам нужно, но имейте в виду, что эта команда перезапишет, а не объединит все изменения рабочего каталога.
Rhubbarb
Это работает для меня, так как я просто хотел скопировать файл, который существует только в тайнике и не заботился checkoutни о чем.
Том Рассел
1
Для Windows PowerShell: git show stash@`{0`}:Path/To/MyFile.txt |sc Path/To/MyFile.txt- галочки необходимы для PS, чтобы не интерпретировать фигурные скобки специально, и scэто необходимо, потому что >оператор PS по умолчанию использует UTF-16 (фактически UCS-2), что, вероятно, не то, что вам нужно. Ответ @Balamurugan A не страдает от этих проблем.
Ян Кемп
19

Первый список всех тайников

git stash list

stash@{0}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{1}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{2}: WIP on master: 7e450c81 Merge branch 'Offlineseite'

Затем покажите, какие файлы находятся в тайнике (давайте выберем тайник 1):

git stash show 1 --name-only

//Hint: you can also write
//git stash show stash@{1} --name-only

 ajax/product.php
 ajax/productPrice.php
 errors/Company/js/offlineMain.phtml
 errors/Company/mage.php
 errors/Company/page.phtml
 js/konfigurator/konfigurator.js

Затем примените файл, который вам нравится:

git checkout stash@{1} -- <filename>

или вся папка:

git checkout stash@{1} /errors

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

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

черный
источник
1
Это яснее с этим редактированием. +1
VonC
1
Я пробовал много способов, и этот путь был тем, который мне был нужен. Я столкнулся с проблемой, которая git stash popвызвала ошибку для неотслеживаемых файлов. благодарю вас.
Рамин Firooz
10

Если вы git stash pop(без конфликтов) он удалит тайник после его применения. Но если вы git stash applyэто примените патч, не удаляя его из списка тайников. Тогда вы можете отменить нежелательные изменения с помощьюgit checkout -- files...

Бен Джексон
источник
2
Чтобы прояснить конфликтную часть этого поста, если вы git stash popи есть конфликты, вам придется их исправить вручную, и тайник НЕ будет удален.
Томас МакКейб
6

Еще один способ:

git diff stash@{N}^! -- path/to/file1 path/to/file2  | git apply -R
Лачо Томов
источник
2
Это единственный правильный ответ ИМО. Использование checkoutили showбудет слепо перезаписывать ваш файл, а не просто вносить изменения. «Еще один путь» - это преуменьшение.
Камбунктив
1
Я не получаю, path/to/file2как вы хотите, чтобы сравнить с тем же файлом в вашей рабочей области. Выход из второго пути работает нормально для меня. - И я получаю сообщение об ошибке, используя -Rопцию («применить патч в обратном порядке», пытаясь исправить патч-версию ?!). Так выглядит моя рабочая версия git diff stash@{N}^! -- path/to/file | git apply -.
ThomasH
"патч не удалось"? Попробуйте 3-х стороннее слияние. ...| git apply -3 -
Джон Ми
6

Для пользователей Windows: фигурные скобки имеют особое значение в PowerShell. Вы можете окружить одинарными кавычками или убежать с помощью backtick. Например:

git checkout 'stash@{0}' YourFile

Без этого вы можете получить сообщение об ошибке:

Unknown switch 'e'

Янак Мина
источник
3
Полная оценка PowerShell за наименее полезное сообщение пользователя, которое я видел в этом месяце.
Holdenweb