Спрятать только один файл из нескольких файлов, которые были изменены с помощью Git?

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


person Rachel    schedule 14.06.2010    source источник
comment
stackoverflow.com/a/19700341/1668622 намного короче принятого ответа, не требует дополнительных инструментов (например, Сценарий Хесуса Фрека), и он прячет только то, что вы хотели спрятать   -  person frans    schedule 08.09.2015
comment
››››››››› git diff -- *filename* > ~/patch, затем git checkout -- *filename* и позже вы можете повторно применить патч с помощью git apply ~/patch   -  person neaumusic    schedule 23.12.2015
comment
Большинство существующих ниже ответов устарели. Начиная с Git 2.13 (второй квартал 2017 г.) он поддерживается git stash push [--] [<pathspec>...].   -  person Ohad Schneider    schedule 15.08.2017


Ответы (33)


git stash push -p -m "my commit message"

-p давайте выберем фрагменты, которые нужно спрятать; также могут быть выбраны целые файлы.

Вам будет предложено выполнить несколько действий для каждого фрагмента:

   y - stash this hunk
   n - do not stash this hunk
   q - quit; do not stash this hunk or any of the remaining ones
   a - stash this hunk and all later hunks in the file
   d - do not stash this hunk or any of the later hunks in the file
   g - select a hunk to go to
   / - search for a hunk matching the given regex
   j - leave this hunk undecided, see next undecided hunk
   J - leave this hunk undecided, see next hunk
   k - leave this hunk undecided, see previous undecided hunk
   K - leave this hunk undecided, see previous hunk
   s - split the current hunk into smaller hunks
   e - manually edit the current hunk
   ? - print help
person konrad.kruczynski    schedule 31.07.2013
comment
@MatthieuNapoli, ты уверен? Это действительно быстро, и справка отображается вверху. q (quit) - не прятать текущий кусок или любой оставшийся (все) - этот кусок, и все, что после d (done-with-this-file) - не прятать этот кусок, или все, что осталось в этом файле / (поиск) - поиск фрагмента e (редактировать) - редактирование текущего фрагмента вручную - person msouth; 13.04.2015
comment
Я наркоман TortoiseGit. Однако TortoiseGit не поддерживает stash -p. Я награждаю этот ответ, потому что он остается наиболее интерактивным / удобным для пользователя. - person Antonio; 15.04.2015
comment
вы можете добавить: git stash save -p my stash message; поскольку порядок аргументов не очень интуитивно понятен ... - person Chris Maes; 23.04.2015
comment
git stash -p не поддерживает неотслеживаемые файлы. Для более легкого и частого использования этот простой сценарий в моем ответе на повторяющийся вопрос позволяет указать, какие файлы следует зафиксировать, и поддерживает как отслеживаемые , так и неотслеживаемые файлы. - person ZimbiX; 22.03.2017
comment
Между этим и git log -p, я думаю, флаг -p должен означать, что я делаю то крутое, что я хочу, но не знаю, как выражать. - person Kyle Strand; 23.05.2017
comment
Я восстановил один из модифицированных файлов (тайник) с вашим ответом, но после этого у меня остались неотслеживаемые файлы stashed.diffversion, что это? что я должен делать? - person Benyamin Jafari; 06.08.2018
comment
Я справляюсь с этим с помощью git clean -fd - person Benyamin Jafari; 06.08.2018
comment
Это правильный ответ, но он становится непригодным для использования, если у вас слишком много фрагментов, которые нужно проработать. - person Richard Smith; 12.02.2019
comment
Быстрый призыв ответить на новый вопрос: stackoverflow.com/a/5506483/2661238 от @svick git stash push -m <stash_name> <file_path_to_stash> - person Deep; 23.06.2019
comment
Как мы можем вернуть конкретный кусок? - person blrguy; 13.03.2020
comment
@Antonio Если вы используете VSCode, он предоставляет графический интерфейс для хранения определенных файлов, щелкнув правой кнопкой мыши выбранные файлы в представлении Source Control и выбрав Stash changes. - person Radzor; 20.01.2021

Заявление об ограничении ответственности: следующий ответ предназначен для git до git 2.13. Для git 2.13 и более поздних версий ознакомьтесь с другим ответом ниже.


Предупреждение

Как отмечено в комментариях, это помещает все в тайник, как постановочное, так и неустановленное. --Keep-index просто оставляет индекс в покое после завершения хранения. Это может вызвать конфликты слияния, когда вы позже откроете тайник.


Это сохранит все, что вы ранее не добавляли. Просто git add то, что вы хотите сохранить, а затем запустите.

git stash --keep-index

Например, если вы хотите разбить старую фиксацию на несколько наборов изменений, вы можете использовать эту процедуру:

  1. git rebase -i <last good commit>
  2. Отметьте некоторые изменения как edit.
  3. git reset HEAD^
  4. git add <files you want to keep in this change>
  5. git stash --keep-index
  6. При необходимости исправьте ситуацию. Не забывайте git add любые изменения.
  7. git commit
  8. git stash pop
  9. При необходимости повторите, начиная с №5.
  10. git rebase --continue
person bukzor    schedule 30.11.2011
comment
Я использовал это, чтобы разделить некоторые изменения, которые не были связаны между собой, используя rebase -i, и это отлично сработало. Я добавил файлы, над которыми хотел поработать, спрятал, как указано выше, исправил что-то по мере необходимости, зафиксировал, спрятал всплывающее окно и повторил. - person bukzor; 05.12.2011
comment
да, я только что заметил, что для перехода в исходное состояние - это чистая промежуточная область, и только с некоторыми выбранными неустановленными модификациями можно мягко сбросить индекс, чтобы получить (без фиксации чего-либо, как вы). неважно, и спасибо за информацию! :) - person Dmitry Avtonomov; 07.12.2011
comment
Это почти хорошо работает, но не хранит вновь добавленные файлы. какое-нибудь решение для этого? - person Guy; 17.04.2012
comment
Я считаю, что этот подход намного проще: stackoverflow.com/a/5506483/457268 - person k0pernikus; 03.09.2012
comment
Я не уверен, почему за это голосуют. У всех должны быть разные ожидания, чем у меня. В исходном сообщении спрашивается, как мне спрятать только часть незафиксированных изменений? Когда я использую git stash save -k, да, индекс (зеленый в git stat) сохраняется, но весь набор изменений (зеленый и красный) попадает в тайник. Это нарушает запрос OP, оставьте только некоторые изменения. Я хочу припрятать немного красного (для использования в будущем). - person Pistos; 07.12.2012
comment
Если вас больше интересует ответ на вопрос, заданный @Pistos (как и меня), посмотрите здесь: stackoverflow.com/questions/5506339/ - person Raman; 17.03.2013
comment
@Raman: Отлично! git stash -p это именно то, что я искал. Интересно, добавили ли этот переключатель совсем недавно? - person Pistos; 10.04.2013
comment
Я попробовал это, и все файлы были добавлены в тайник, даже те, которые были поставлены. - person b01; 13.04.2013
comment
ВНИМАНИЕ: git stash --keep-index сломан. Если вы внесете больше изменений, попробуйте git stash pop позже вы получите конфликты слияния, потому что тайник включает измененные файлы, которые вы сохранили, а не только те, которые вы не сохранили. Например: я меняю файлы A и B, а затем прячу B, потому что хочу проверить изменения в A; Я нахожу проблему с A, которую затем исправляю; Я совершаю A; Теперь я не могу разблокировать, потому что старая версия A находится в тайнике без уважительной причины, вызывая конфликт слияния. На практике A и B могут быть множеством файлов, возможно, даже двоичными изображениями или чем-то в этом роде, поэтому мне в основном приходится сдаваться и терять B. - person rjmunro; 26.02.2014
comment
Это не только то, что он не отвечает на вопрос, но и вводит в заблуждение. Сказав это, вы закроете все, что вы ранее не добавляли. предполагает, что когда вы добавляете файл с помощью git, он не будет сохранен. Это не случай. Не могу понять, почему он отмечен как ответ и получил столько голосов. - person amfcosta; 16.02.2016
comment
Что забавно, так это то, что другой вопрос SO в ссылке @Raman, который отвечает на вопрос более прямо, помечен как дубликат этого :( - person x6iae; 17.02.2016
comment
@Pistos Я подозреваю, что когда-то этот ответ был правильным, но функциональность была нарушена в каком-то выпуске Git вскоре после того, как он был написан. Пример Тестирование частичных коммитов на git-scm.com/docs/git -stash очень ясно показывает, что предполагаемое поведение --keep-index - это именно то, что утверждает этот ответ, но, как вы указываете, фактическое поведение совершенно иное. И все же это не исправлялось годами! Какой беспорядок. - person Mark Amery; 06.08.2016
comment
ахаха невероятно, как ответ на СОВЕРШЕННО другой вопрос, чем заданный OP, может иметь +1000, смеется :) Вопрос был о git stash -p - person DenisFLASH; 09.01.2018
comment
за этот вопрос не было бы так много голосов, если бы за правильным ответом (git stash -p) не было так далеко до прокрутки (12-я позиция на мгновение). Что происходит, ТАК? :) - person DenisFLASH; 09.01.2018
comment
Это определенно НЕ правильный ответ, использование --keep-index не будет хранить только некоторые файлы, оно сохранит ВСЕ ваши файлы. - person sapeish; 10.05.2018

Начиная с Git 2.13 (второй квартал 2017 г.), вы можете хранить отдельные файлы с помощью _ 1_:

git stash push [-m <message>] [--] [<pathspec>...]

Когда pathspec присвоено 'git stash push', новый тайник записывает измененные состояния только для файлов, соответствующих указанному пути. См. Изменения тайника для определенных файлов, чтобы узнать больше.

Упрощенный пример:

 git stash push path/to/file

Тестовый пример для этой функции показывает еще несколько вариантов выключены:

test_expect_success 'stash with multiple pathspec arguments' '
    >foo &&
    >bar &&
    >extra &&
    git add foo bar extra &&

    git stash push -- foo bar &&   

    test_path_is_missing bar &&
    test_path_is_missing foo &&
    test_path_is_file extra &&

    git stash pop &&
    test_path_is_file foo &&
    test_path_is_file bar &&
    test_path_is_file extra

Первоначальный ответ (ниже, июнь 2010 г.) касался ручного выбора того, что вы хотите спрятать.

Комментарии Casebash:

Это (исходное решение stash --patch) приятно, но я часто изменял много файлов, поэтому использование патча раздражает

ответ от bukzor (проголосовано за ноябрь 2011 г.) предлагает более практичное решение, основанное на
git add + git stash --keep-index.
Посмотрите и проголосуйте за его ответ, который должен быть официальным (вместо этого мой).

Об этом варианте chhh указывает в комментариях на альтернативный рабочий процесс:

вы должны git reset --soft после такого тайника вернуть четкую постановку:
Чтобы вернуться к исходному состоянию, которое является чистой промежуточной областью и только с некоторыми избранными неустановленными модификациями, можно мягко сбросить индекс до получить (не совершая ничего подобного вам - букзор - сделал).


(Исходный ответ июнь 2010 г .: тайник вручную)

Тем не менее, git stash save --patch может позволить вам добиться частичного хранения, которое вам нужно:

С --patch вы можете в интерактивном режиме выбирать блоки из разницы между HEAD и рабочим деревом, которое нужно сохранить.
Запись в тайнике построена так, что ее состояние индекса совпадает с состоянием индекса вашего репозитория и его рабочего дерева содержит только те изменения, которые вы выбрали в интерактивном режиме. Затем выбранные изменения откатываются от вашего рабочего дерева.

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

git stash --patch --no-keep-index

может быть лучше.


Если --patch не работает, ручной процесс может:

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

  • скопируйте их за пределы репозитория Git
    (на самом деле eleotlecram предлагает интересная альтернатива)
  • git stash
  • скопируйте их обратно
  • git stash # на этот раз сохраняются только те файлы, которые вам нужны
  • git stash pop stash@{1} # повторно примените все изменения ваших файлов
  • git checkout -- afile # сбросить файл до содержимого HEAD перед любыми локальными изменениями

В конце этого довольно громоздкого процесса у вас останется только один или несколько файлов.

person VonC    schedule 14.06.2010
comment
Это хорошо, но я часто изменял много файлов, поэтому использование патча раздражает - person Casebash; 16.11.2011
comment
@Casebash: Тогда посмотрите мой ответ ниже. - person bukzor; 07.12.2011
comment
Я не совсем понимаю, почему я должен выполнять git reset --soft после git stash --keep-index. Мягкий сброс не затрагивает индекс, так как же это имеет значение в отношении промежуточной обработки? - person Kal; 22.03.2013
comment
@Kal: верно, stackoverflow.com/a/13941132/6309 предлагает git reset (смешанный) - person VonC; 22.03.2013
comment
git is fundamentally about managing a all repository content and index and not one or several files - это реализация, затмевающая решаемую проблему; это объяснение, но не оправдание. Любая система контроля версий - это управление несколькими файлами. Просто посмотрите, какие комментарии получают больше всего голосов. - person Victor Sergienko; 23.12.2015
comment
-1 за рекомендацию git stash --keep-index; как отмечено в комментариях к ответу букзора, он просто не делает то, что вы думаете. Создайте два файла foo и bar. Зафиксируйте их. Добавьте строчку к каждому. git add foo. git stash --keep-index. Теперь желаемый результат состоит в том, что ваше изменение в bar спрятано, а изменение в foo все еще присутствует и находится в стадии постановки. На самом деле изменения в foo присутствуют и поставлены, но изменения в обоих файлах спрятаны. Если вы git reset и измените foo, теперь вы не сможете git stash pop из-за конфликта. - person Mark Amery; 06.08.2016
comment
Это было безумием, по крайней мере, здравый смысл начал преобладать. Теперь мне нужно узнать, как обновить MacOSX Git до 2.13. - person Ed Randall; 08.08.2017
comment
Это также спрятало все подготовленные файлы. Поэтому убедитесь, что вы не вносили никаких изменений - person Ville Miekk-oja; 31.03.2020

Используйте git stash push, например:

git stash push [--] [<pathspec>...]

Например:

git stash push -- my/file.sh

Это доступно, начиная с Git 2.13, выпущенного весной 2017 года.

person sandstrom    schedule 15.08.2017
comment
Но я упоминаю git stash push уже в моем ответе выше в марте прошлого года, 5 месяцев назад. И я подробно описал эту новую команду Git 2.13 здесь: stackoverflow.com/a/42963606/6309. - person VonC; 15.08.2017
comment
Я счастлив, что Git продвигается так быстро, долгое время это было невозможно, а затем была выпущена версия 2.13, и внезапно стало доступно простое решение! - person sandstrom; 23.01.2018
comment
@VonC, вы правы, вы также упоминаете правильный ответ, однако между двумя ответами этот легче читать (нет запутанного текста, а также есть пример). Может, им стоило вместо этого отредактировать твой ответ - person Utopik; 11.10.2018
comment
@Utopik Вы правы ... но да, я отредактировал свой ответ, включив в него пример. - person VonC; 11.10.2018
comment
Можно ли затем использовать git stash apply для восстановления сохраненных изменений? - person Chad; 22.11.2019
comment
Может ли кто-нибудь просветить меня, почему такое неясное слово «pathspec» используется для обозначения пути к файлу? Или это не так уж непонятно, как я думаю? - person Nikhil Vandanapu; 21.02.2020
comment
@NikhilVandanapu Я думаю, термин pathspec используется, потому что это может быть больше, чем простой путь. Он может включать стандартные подстановочные знаки, подстановочные знаки с двумя звездочками и даже более эзотерический синтаксис. Для получения дополнительной информации перейдите на https://git-scm.com/docs/gitglossary и ищите pathspec. - person Simpleton; 07.10.2020

Когда git stash -p (или git add -p с stash --keep-index) было бы слишком громоздко, мне было проще использовать diff, checkout и apply:

Чтобы "спрятать" только определенный файл / каталог:

git diff path/to/dir > stashed.diff
git checkout path/to/dir

Потом потом

git apply stashed.diff
person blueyed    schedule 12.02.2014
comment
Интересная альтернатива git add -p, о которой я упоминал в своем ответе выше. +1. - person VonC; 12.02.2014
comment
Обратите внимание, что если у вас есть двоичные файлы (например, PNG), они не будут выводиться в файл сравнения. Так что это не стопроцентное решение. - person void.pointer; 13.03.2014
comment
@RobertDailey: Это интересный момент для меня, поскольку git diff > file.diff и git apply - мои обычные инструменты частичного хранения. Возможно, мне придется подумать о переходе на git stash -p для более крупных изменений. - person thekingoftruth; 20.06.2014
comment
@thekingoftruth Вот псевдоним, который я использую для создания файлов патчей, и он поддерживает двоичные файлы: patch = log --pretty=email --patch-with-stat --reverse --full-index --binary. Обратите внимание, однако, что это требует, чтобы ваши изменения были зафиксированы. - person void.pointer; 23.06.2014
comment
Это не сработало для меня, если файл для хранения был чем-то вроде ../../foo/bar.txt. Патч работает нормально, но затем мне нужно перейти в корень репозитория, чтобы применить патч. Так что, если у вас возникли проблемы с этим - просто убедитесь, что вы делаете это из корневого каталога репозитория. - person Michael Anderson; 03.06.2016

Допустим, у вас есть 3 файла

a.rb
b.rb
c.rb

и вы хотите спрятать только b.rb и c.rb, но не a.rb

ты можешь сделать что-то вроде этого

# commit the files temporarily you don't want to stash
git add a.rb
git commit -m "temp" 

# then stash the other files
git stash save "stash message"

# then undo the previous temp commit
git reset --soft HEAD^
git reset

Готово! HTH.

person venkatareddy    schedule 31.10.2013

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

$ git stash -- filename.ext

Если это не отслеживаемый / новый файл, вам сначала нужно его обработать.

Этот метод работает в версиях git 2.13+.

person sealocal    schedule 09.03.2019
comment
Этот ответ многословен, он краток. Если это кому-то поможет, оставлю. Никто на этой странице не упоминает этот синтаксис и результат - вместо этого они упоминают `git stash push`. - person sealocal; 09.03.2019
comment
Это тот ответ, который я искал. Спасибо! +1 - person nicodp; 28.03.2020

Другой способ сделать это:

# Save everything
git stash 

# Re-apply everything, but keep the stash
git stash apply

git checkout <"files you don't want in your stash">

# Save only the things you wanted saved
git stash

# Re-apply the original state and drop it from your stash
git stash apply stash@{1}
git stash drop stash@{1}

git checkout <"files you put in your stash">

Я придумал это после того, как (еще раз) зашел на эту страницу, и мне не понравились первые два ответа (первый ответ просто не отвечает на вопрос, и мне не очень понравилось работать в интерактивном режиме -p).

Идея такая же, как и в случае с предложением @VonC использовать файлы вне репозитория: вы где-то сохраняете нужные изменения, удаляете ненужные изменения в своем тайнике, а затем повторно применяете изменения, которые вы убрали с пути. Тем не менее, я использовал git stash как «где-то» (и в результате есть один дополнительный шаг в конце: удаление изменений, которые вы вставляете в тайник, потому что вы их тоже убрали).

person Jasper    schedule 05.02.2015
comment
Я больше всего предпочитаю этот подход. Он обеспечивает простой рабочий процесс в tortoisegit, используя только команды stash и revert. - person Mark Ch; 01.02.2016
comment
Обращаться к ответам на SO с использованием позиций не рекомендуется. Позиции меняются по мере изменения рейтинга. - person Bryan Ash; 01.06.2016
comment
@BryanAsh Ну, здесь это не имеет значения. Я даю анекдот, а не ссылаюсь на другие ответы. Суть в том, что мне не нравились ответы, которые понравились сообществу, а не то, что они на самом деле содержат. Кроме того, разница в 900 голосов между вторым и третьим ответами делает это маловероятным, чтобы это изменилось в ближайшем будущем, и если оно когда-либо изменится, я всегда могу отредактировать его, чтобы указать верхние ответы на тот момент. На самом деле, я не понимаю, как это вообще может быть проблемой в данной ситуации. - person Jasper; 01.06.2016

Обновление (14.02.2015). Я немного переписал сценарий, чтобы лучше справляться с конфликтами, которые теперь должны быть представлены как несвязанные конфликты, а не как файлы .rej.


Я часто нахожу более интуитивным подход, противоположный подходу @bukzor. То есть провести некоторые изменения, а затем спрятать только эти поэтапные изменения.

К сожалению, git не предлагает git stash --only-index или аналогичный, поэтому я создал для этого скрипт.

#!/bin/sh

# first, go to the root of the git repo
cd `git rev-parse --show-toplevel`

# create a commit with only the stuff in staging
INDEXTREE=`git write-tree`
INDEXCOMMIT=`echo "" | git commit-tree $INDEXTREE -p HEAD`

# create a child commit with the changes in the working tree
git add -A
WORKINGTREE=`git write-tree`
WORKINGCOMMIT=`echo "" | git commit-tree $WORKINGTREE -p $INDEXCOMMIT`

# get back to a clean state with no changes, staged or otherwise
git reset -q --hard

# Cherry-pick the index changes back to the index, and stash.
# This cherry-pick is guaranteed to succeed
git cherry-pick -n $INDEXCOMMIT
git stash

# Now cherry-pick the working tree changes. This cherry-pick may fail
# due to conflicts
git cherry-pick -n $WORKINGCOMMIT

CONFLICTS=`git ls-files -u`
if test -z "$CONFLICTS"; then
    # If there are no conflicts, it's safe to reset, so that
    # any previously unstaged changes remain unstaged
    #
    # However, if there are conflicts, then we don't want to reset the files
    # and lose the merge/conflict info.
    git reset -q
fi

Вы можете сохранить приведенный выше скрипт как git-stash-index где-нибудь на своем пути, а затем вызвать его как git stash-index

# <hack hack hack>
git add <files that you want to stash>
git stash-index

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

В некоторых случаях изменения рабочего дерева могут зависеть от изменений индекса, поэтому, когда вы сохраняете изменения индекса, изменения рабочего дерева конфликтуют. В этом случае вы получите обычные конфликты без объединения, которые можно разрешить с помощью git merge / git mergetool / etc.

person JesusFreke    schedule 16.06.2013
comment
Рекомендуйте pushd вместо cd и popd в конце сценария, чтобы, если сценарий завершился успешно, пользователь попал в тот же каталог, что и до его запуска. - person Nate; 23.03.2015
comment
@Nate: насколько я знаю, он должен изменять каталог для пользователя только в том случае, если они получили скрипт. Если вы запускаете скрипт в обычном режиме (~ / bin / git-stash-index) или через git (git stash-index), он запускается в отдельном сеансе терминала, и любые изменения рабочего каталога в этом сеансе не влияют на рабочий каталог в терминальной сессии пользователя. Известно ли вам о распространенном случае, когда это неправда? (кроме поиска скрипта, что я бы не стал считать обычным) - person JesusFreke; 23.03.2015

Вы можете просто сделать это:

git stash push "filename"

или с необязательным сообщением

git stash push -m "Some message" "filename"
person vinodsaluja    schedule 21.05.2019
comment
Это не добавляет ничего нового. Git stash push уже упоминается в нескольких ответах - person JesusFreke; 28.05.2019
comment
git stash push -- <filepath> - это то, что сработало для меня, и добавлено в недавнюю версию GIT (v2.13 ›) в качестве решения. Вы можете получить ‹filepath›, если запустите git status. - person Samir K; 20.08.2020
comment
@SamirK Спасибо за комментарий, мне это помогло - person Chakri; 20.01.2021

Поскольку создание веток в Git тривиально, вы можете просто создать временную ветку и проверить в ней отдельные файлы.

person shangxiao    schedule 28.06.2011
comment
Вы не можете создать ветку с неустановленными правками. Вы можете легко переместить все правки в новую ветку (stash / stash pop), но тогда вы вернетесь к исходной точке: как вы протестируете свою ветку только с некоторыми из этих изменений, не теряя другие? - person bukzor; 07.12.2011
comment
Вы не можете переключать ветки, если у вас есть локальные изменения. Однако вы можете создать новую ветку и выборочно добавлять / фиксировать файлы, а затем создать другую ветку и сделать то же самое рекурсивно ... затем проверить исходную ветвь и выборочно слить обратно. Я только что сделал это. На самом деле это кажется естественным способом делать что-то, поскольку вы, по сути, создаете ветки функций. - person iain; 17.02.2012
comment
@iain вы можете переключать ветки, если у вас есть локальные изменения, если они не требуют слияния. См. Пример Gist. Это верно как минимум для Git v2.7.0. - person Colin D Bennett; 18.02.2016

Если вы хотите сохранить только некоторые из измененных файлов, просто добавьте другие файлы в Stage, затем выполните git stash push --keep-index

Он сохранит все неустановленные измененные файлы.

person Amin Shojaei    schedule 12.12.2019
comment
Параметр save устарел в пользу git stash push. Вместо этого можно было просто использовать git stash push --keep-index. - person Song WANG; 26.04.2021
comment
Спасибо за обновление. ответ отредактирован. @SongWANG - person Amin Shojaei; 26.04.2021

Сохраните следующий код в файл, например, с именем stash. Использование stash <filename_regex>. Аргумент - это регулярное выражение для полного пути к файлу. Например, чтобы спрятать a / b / c.txt, stash a/b/c.txt или stash .*/c.txt и т. Д.

$ chmod +x stash
$ stash .*.xml
$ stash xyz.xml

Код для копирования в файл:

#! /usr/bin/expect --
log_user 0
set filename_regexp [lindex $argv 0]

spawn git stash -p

for {} 1 {} {
  expect {
    -re "diff --git a/($filename_regexp) " {
      set filename $expect_out(1,string)
    }
    "diff --git a/" {
      set filename ""
    }
    "Stash this hunk " {
      if {$filename == ""} {
        send "n\n"
      } else {
        send "a\n"
        send_user "$filename\n"
      }
    }
    "Stash deletion " {
      send "n\n"
    }
    eof {
      exit
    }
  }
}
person apricot    schedule 11.07.2014
comment
Отличный метод. Я бы выбрал это в качестве ответа. Совет для будущих читателей: вы должны соответствовать по полному пути. например поддиректория тайника / foo.c - person er0; 21.10.2014

На всякий случай вы действительно имеете в виду отменить изменения всякий раз, когда используете git stash (и на самом деле не используете git stash для его временного хранения), в этом случае вы можете использовать

git checkout -- <file>

[ПРИМЕЧАНИЕ]

Этот git stash - всего лишь более быстрая и простая альтернатива ветвлению и работе.

person Devesh    schedule 19.12.2014

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

А проще использовать tar (вероятно, подойдут аналогичные инструменты) вместо копирования:

  • tar cvf /tmp/stash.tar path / to / some / file path / to / some / other / file (... и т. д.)
  • git checkout path / to / some / путь к файлу / to / some / other / file
  • мерзавец
  • tar xvf /tmp/stash.tar
  • и т. д. (см. "промежуточное" предложение VonC)
person eleotlecram    schedule 27.09.2011
comment
checkout -f не нужен, достаточно checkout (без -f), ответ обновил. - person eleotlecram; 08.12.2011

Иногда я вносил несвязанные изменения в свою ветку до того, как зафиксировал их, и я хочу переместить их в другую ветку и зафиксировать отдельно (например, master). Я делаю это:

git stash
git checkout master
git stash pop
git add <files that you want to commit>
git commit -m 'Minor feature'
git stash
git checkout topic1
git stash pop
...<resume work>...

Обратите внимание, что первый stash & stash pop можно исключить, вы можете перенести все свои изменения в ветку master при оформлении заказа, но только если нет конфликтов. Также, если вы создаете новую ветку для частичных изменений, вам понадобится тайник.

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

git checkout master
git add <files that you want to commit>
git commit -m 'Minor feature'
git checkout topic1
...<resume work>...

Тайник даже не нужен ...

person void.pointer    schedule 13.03.2014

Это можно легко сделать за 3 шага с помощью SourceTree.

  1. Временно зафиксируйте все, что вы не хотите прятать.
  2. Git добавляет все остальное, а затем прячет.
  3. Удалите временную фиксацию, запустив git reset, выбрав фиксацию перед временной.

Все это можно сделать за считанные секунды в SourceTree, где вы можете просто щелкнуть файлы (или даже отдельные строки), которые хотите добавить. После добавления просто зафиксируйте их во временной фиксации. Затем установите флажок, чтобы добавить все изменения, затем щелкните тайник, чтобы спрятать все. Убрав спрятанные изменения в сторону, взгляните на свой список коммитов и обратите внимание на хэш для фиксации перед временной фиксацией, затем запустите 'git reset hash_b4_temp_commit', что в основном похоже на «выталкивание» фиксации путем сброса вашей ветки на совершить прямо перед этим. Теперь у вас осталось только то, что вы не хотели прятать.

person Triynko    schedule 11.01.2016

Я бы использовал git stash save --patch. Я не считаю интерактивность раздражающей, потому что во время нее есть опции, позволяющие применить желаемую операцию ко всем файлам.

person Raffi Khatchadourian    schedule 13.04.2017
comment
Удивлен, что у этого ответа так мало поддержки, что это лучшее решение, не требующее сочинения. - person robstarbuck; 04.09.2017
comment
Определенно хороший ответ, git stash -p позволяет быстро спрятать весь файл и после этого выйти. - person Richard Dally; 07.12.2017

Каждый ответ здесь такой сложный ...

А как насчет этого «припрятать»:

git diff /dir/to/file/file_to_stash > /tmp/stash.patch
git checkout -- /dir/to/file/file_to_stash

Это, чтобы вернуть изменение файла:

git apply /tmp/stash.patch

Точно такое же поведение, как при сохранении одного файла и его возвращении.

person Christophe Fondacci    schedule 14.12.2016
comment
Я пробовал, но ничего не получается. Когда я git apply, у меня нет ошибки, но и изменения не возвращаются. - person ClementWalter; 10.04.2017
comment
Файл исправления, созданный вами в / tmp, вероятно, был удален. Возможно, вы перезагрузились между diff и применением. Попробуйте другое более постоянное место. Это действительно работает. Также проверьте содержимое файла патча. - person Christophe Fondacci; 12.04.2017

Я просмотрел ответы и комментарии к этой и ряду подобных тем. Имейте в виду, что ни одна из следующих команд не подходит для сохранения каких-либо определенных отслеживаемых / неотслеживаемых файлов:

  • git stash -p (--patch): выбрать блоки вручную, исключая неотслеживаемые файлы
  • git stash -k (--keep-index): хранить все отслеживаемые / неотслеживаемые файлы и хранить их в рабочем каталоге
  • git stash -u (--include-untracked): хранить все отслеживаемые / неотслеживаемые файлы
  • git stash -p (--patch) -u (--include-untracked): недопустимая команда

В настоящее время наиболее разумным методом хранения любых отслеживаемых / неотслеживаемых файлов является:

  • Временно зафиксируйте файлы, которые вы не хотите хранить
  • Добавить и спрятать
  • Удалите временную фиксацию

Я написал простой сценарий для этой процедуры в ответ на другой вопрос, и есть шаги для выполнения процедуры в SourceTree здесь.

person ZimbiX    schedule 22.03.2017

Решение

Локальные изменения:

  • file_A (изменено) не поставлено
  • file_B (изменено) не поставлено
  • file_C (изменено) не поставлено

Чтобы создать тайник my_stash только с изменениями в file_C:

1. git add file_C
2. git stash save --keep-index temp_stash
3. git stash save my_stash
4. git stash pop stash@#{1}

Выполнено.


Объяснение

  1. добавить file_C в область подготовки
  2. создайте временный тайник с именем «temp_stash» и сохраните изменения в file_C
  3. создать желаемый тайник ("my_stash") только с изменениями в file_C
  4. примените изменения в "temp_stash" (file_A и file_B) в вашем локальном коде и удалите тайник

Вы можете использовать git status между шагами, чтобы увидеть, что происходит.

person Alex 75    schedule 29.03.2017

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

Попробуйте добавить файлы с помощью «git add filepath».

Позже выполните эту строку

git stash --keep-index

person Sireesh Yarlagadda    schedule 21.07.2015

Чтобы спрятать один файл, используйте git stash --patch [file].

Появится запрос: Stash this hunk [y,n,q,a,d,j,J,g,/,e,?]? ?. Просто введите a (спрячьте этот кусок и все последующие фрагменты в файл), и все в порядке.

person vinibrsl    schedule 14.09.2018
comment
Отсутствует push, как в git stash push --patch [file] - person Filipe Esperandio; 02.10.2018
comment
@FilipeEsperandio push работает только в более последних версиях Git, используемых для быть _ 2_. В любом случае push или save подразумеваются вызовом stash: вызов git stash без каких-либо аргументов эквивалентен git stash push, документы - person patrick; 14.02.2019

Аналогичная ситуация. Сделал коммит и понял, что это не нормально.

git commit -a -m "message"
git log -p

Судя по ответам, это помогло мне.

# revert to previous state, keeping the files changed
git reset HEAD~
#make sure it's ok
git diff
git status
#revert the file we don't want to be within the commit
git checkout specs/nagios/nagios.spec
#make sure it's ok
git status
git diff
#now go ahead with commit
git commit -a -m "same|new message"
#eventually push tu remote
git push
person David Hrbáč    schedule 20.06.2012

В этой ситуации я git add -p (интерактивно), git commit -m blah, а затем прячу то, что осталось, если необходимо.

person J0hnG4lt    schedule 18.04.2013

Я не знаю, как это сделать в командной строке, только с помощью SourceTree. Допустим, вы изменили файл A и у вас есть два фрагмента изменений в файле B. Если вы хотите спрятать только второй фрагмент в файле B и оставить все остальное нетронутым, сделайте следующее:

  1. Сценическое все
  2. Внесите изменения в вашу рабочую копию, которые отменит все изменения в файле A. (например, запустите внешний инструмент сравнения и сопоставьте файлы.)
  3. Сделайте так, чтобы файл B выглядел так, как будто к нему применяется только второе изменение. (например, запустить внешний инструмент сравнения и отменить первое изменение.)
  4. Создайте тайник, используя «Сохранять поэтапные изменения».
  5. Убрать все на сцену
  6. Выполнено!
person Juozas Kontvainis    schedule 30.04.2015

Для пользователей VS Code. Кнопка тайника для группы Изменения в представлении боковой панели Git сохранит только файлы в группе. Поэтому, если вы переместите некоторые файлы из этой группы, вы можете спрятать оставшиеся файлы. Единственный известный мне способ переместить некоторые файлы оттуда без отмены изменений - это выполнить их. Так:

  1. Подготовьте файлы, которые вы не хотите прятать
  2. Нажмите кнопку тайника в заголовке группы Изменения.
  3. Отключите файлы, которые вы переместили с пути
person PEZ    schedule 27.05.2021

Один из сложных способов - сначала зафиксировать все:

git add -u
git commit // creates commit with sha-1 A

Вернитесь к исходной фиксации, но проверьте the_one_file из новой фиксации:

git reset --hard HEAD^
git checkout A path/to/the_one_file

Теперь вы можете спрятать the_one_file:

git stash

Очистка путем сохранения зафиксированного содержимого в файловой системе с возвратом к исходной фиксации:

git reset --hard A
git reset --soft HEAD^

Ага, несколько неловко ...

person Martin G    schedule 08.02.2017

Я не нашел того, что мне было нужно, и это очень просто:

git add -A
git reset HEAD fileThatYouWantToStash
git commit -m "committing all but one file"
git stash

Это хранит ровно один файл.

person SCBuergel    schedule 27.02.2017

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

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

person superarts.org    schedule 23.04.2020

Быстрый ответ


Чтобы вернуть конкретный измененный файл в git, вы можете сделать следующую строку:

git checkout <branch-name> -- <file-path>

Вот реальный пример:

git checkout master -- battery_monitoring/msg_passing.py

person Benyamin Jafari    schedule 07.08.2018

Вы также можете сохранить только один файл, коллекцию файлов или отдельные изменения внутри файлов. Если вы передадите параметр -p (или --patch) в git stash, он будет перебирать каждый измененный «кусок» в вашей рабочей копии и спрашивать, хотите ли вы его спрятать:

$ git stash -p

нажмите одну из клавиш, как показано ниже, и она запустит эту команду

Command   Description 
y         stash this hunk  
/         search for a hunk by regex .  
?         help .   
n         don't stash this hunk .    
q         quit (any hunks that have already been selected will be stashed) .   
s         split this hunk into smaller hunks    
person abhishek ringsia    schedule 25.02.2020
comment
дублирующийся ответ на stackoverflow.com/a/17969785/728287 - person Gianfranco P.; 10.03.2020

person    schedule
comment
Что ж, не надо этого делать. Ответ должен дать ответ на вопрос. Вы можете просто задать свой вопрос. - person L_J; 20.07.2018
comment
это решение - один из самых простых ответов на ЭТОТ вопрос. прочитайте вопрос, сравните все ответы и мой, тогда, если вы сомневаетесь, что этот ответ не является ни применимым решением, ни недостаточной информацией по вопросу, тогда мы можем поговорить снова. - person celikz; 20.07.2018
comment
Это не сработает, потому что третья команда, git stash, не будет учитывать поэтапные файлы. И поэтапные, и неэтапные файлы попадут в тайник. Вопросы конкретно спрашивают, как спрятать только один файл - person CyberProdigy; 27.02.2019