Как мне извлечь один файл (или изменения в файл) из git stash? - PullRequest
654 голосов
/ 09 июля 2009

Хотелось бы узнать, возможно ли извлечь отдельный файл или diff из файла из git stash, не отключая набор изменений stash.

Может ли кто-нибудь предоставить некоторые предложения / идеи по этому поводу?

Ответы [ 8 ]

968 голосов
/ 09 июля 2009

На странице git stash вы можете прочитать это (в разделе "Обсуждение", сразу после описания "Опции"):

Тайник представляется как коммит, дерево которого записывает состояние рабочий каталог, и его первым родителем является коммит в HEAD, когда заначка была создана.

Таким образом, вы можете рассматривать stash (например, stash@{0} - это первый / самый верхний тайник) как коммит слияния и использовать:

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

Объяснение: stash@{0}^1 ярлык означает первого родителя данного тайника, который, как указано в объяснении выше, является коммитом, при котором изменения были спрятаны. Мы используем эту форму "git diff" (с двумя коммитами), потому что stash@{0} / refs/stash является коммитом слияния, и мы должны указать git, против какого родителя мы хотим использовать diff. Более загадочный:

$ git diff stash@{0}^! -- <filename>

также должен работать (см. Справочную страницу rev^! в разделе «Задание диапазонов» для справки git rev-parse ).

Аналогично, вы можете использовать git checkout , чтобы проверить один файл из тайника:

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

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

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

или

$ git show stash@{0}:./<relative filename> > <newfile>

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


Возможно, вам потребуется защитить stash@{0} от расширения оболочки, т. Е. Использовать "stash@{0}" или 'stash@{0}'.

37 голосов
/ 09 июля 2009

Если вы используете git stash apply вместо git stash pop, он будет применять тайник к вашему рабочему дереву, но все равно сохранит тайник.

После этого вы можете add / commit файл, который вы хотите, а затем сбросить оставшиеся изменения.

19 голосов
/ 22 декабря 2015

Краткий ответ

Для просмотра всего файла: git show stash@{0}:<filename>

Чтобы увидеть разницу: git diff stash@{0}^1 stash@{0} -- <filename>

17 голосов
/ 26 июня 2017

Существует простой способ получить изменения из любой ветки, включая тайники:

$ git checkout --patch stash@{0} path/to/file

Вы можете опустить спецификацию файла, если вы хотите патчить во многих частях. Или пропустите патч (но не путь), чтобы получить все изменения в одном файле. Замените 0 номером тайника из git stash list, если у вас их больше одного. Обратите внимание, что это похоже на diff и предлагает применить все различия между ветвями. Чтобы получить изменения только от одного коммита / тайника, взгляните на git cherry-pick --no-commit.

12 голосов
/ 08 сентября 2017
$ git checkout stash@{0} -- <filename>

Примечания:

  1. Убедитесь, что вы ставите пробел после "-" и параметра имени файла

  2. Замените ноль (0) вашим конкретным номером тайника. Чтобы получить список тайников, используйте:

    git stash list
    

На основании ответа Якуба Наребски - более короткая версия

10 голосов
/ 09 июля 2009

Вы можете получить diff для тайника с помощью «git show stash@{0}» (или любого другого номера тайника; см. «Список git stash»). Легко извлечь раздел diff для одного файла.

5 голосов
/ 19 июля 2010

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

Если вы сделаете git stash, чтобы спрятать их все, git stash apply, чтобы вернуть их снова, а затем git checkout f.c в рассматриваемом файле, чтобы эффективно сбросить его.

Когда вы хотите распаковать этот файл, выполните git reset --hard, а затем снова запустите git stash apply, воспользовавшись тем, что git stash apply не очищает diff из стека хранилища.

1 голос
/ 26 октября 2017

Если спрятанные файлы необходимо объединить с текущей версией, используйте предыдущие способы, используя diff. В противном случае вы можете использовать git pop для их удаления, git add fileWantToKeep для размещения вашего файла и сделать git stash save --keep-index для хранения всего, кроме того, что находится на сцене. Помните, что отличие этого способа от предыдущих заключается в том, что он «выталкивает» файл из stash. Предыдущие ответы держат его git checkout stash@{0} -- <filename>, поэтому он идет в соответствии с вашими потребностями.

...