Копить только один файл из нескольких файлов, которые были изменены до git 2.13 - PullRequest
2764 голосов
/ 15 июня 2010

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

Ответы [ 29 ]

2906 голосов
/ 31 июля 2013

Вы также можете использовать git stash save -p "my commit message".Таким образом, вы можете выбрать, какие блоки должны быть добавлены в тайник, а также целые файлы.

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

   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
1295 голосов
/ 01 декабря 2011

Обновление следующий ответ для git перед git 2.13.Для git 2.13 и выше, посмотрите Как я могу git спрятать определенный файл?

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

Как отмечено в комментариях, это ставитвсе в тайник, как постановочное, так и не постановочное.--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
344 голосов
/ 15 июня 2010

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

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

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

Когда pathspec присваивается 'git stash push', новый тайник записывает измененные состояния только для файлов, которые соответствуют пути

Подробнее см. " Хранение изменений в определенных файлах ".

Контрольный пример не требует пояснений:

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) хорошо, но часто я модифицировал много файлов, поэтому использование патча раздражает

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

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

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


(Оригинальный ответ, июнь 2010 г .: тайник с ручным управлением)

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

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

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

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

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


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

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

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

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

81 голосов
/ 12 февраля 2014

Когда 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
67 голосов
/ 15 августа 2017

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

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

Например:

git stash push -- my/file.sh

Доступно с Git 2.13, выпущенной весной 2017 года.

45 голосов
/ 31 октября 2013

Допустим, у вас есть 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

И все готово! НТН.

28 голосов
/ 05 февраля 2015

Еще один способ сделать это:

# 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 как «где-то» (и, как результат, в конце есть еще один дополнительный шаг: удаление канавок, которые вы положили в тайник, потому что вы также убрали их с пути).

23 голосов
/ 17 июня 2013

Обновление (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 / и т. Д.

19 голосов
/ 28 июня 2011

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

11 голосов
/ 19 декабря 2014

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

git checkout -- <file>

[ NOTE ]

То, что git stash - это просто более быстрая и простая альтернатива ветвлению и выполнению задач.

...