Периодически появляется необходимость сделать stash не всех измененных файлов, а только некоторых. Как это реализовать? Да, есть git stash --keep-index (--no-keep-index) или git stash --patch. Но (тут я могу ошибаться) ни то ни другое не дает мне полного контроля над происходящим. С флагом --keep-index в stash добавятся все staged файлы(to be committed, как сделал бы обычный commit, то что нужно), а также все not staged for commit в придачу, чего мне совсем не нужно. Почему нельзя просто добавить в stash только те, которые готовы к коммиту? Как вариант, чтобы добиться нужного результата, можно делать коммиты, а потом их отменять, но это уже какой-то намек на мусье, который знает толкъ...
Спасибо.
UPD. Спасибо всем ответившим.
Краткое резюме: добавить в stash только выбранные файлы не получится. Если такая необходимость возникла, то скорее всего Вы используете git неправильно. Посмотрите в сторону других схем использования гита: rebase, cherry-pick, merge workflows.
Вы на стэш смотрите немного не правильно, он не предназначен для подготовки комитов.
Он предназначит для того что бы спрятать не нужные на данный момент изменения, потому он и называется stash, в переводе — прятать, припрятывать.
Летят Холмс с Ватсоном на воздушном шаре. И спят в полете. Просыпаются
над какой-то незнакомой землей, видят — внизу какой-то хрен коров пасет.
Снизились они и спрашивают мужика:
— Скажите, сэр, где мы находимся?
— На воздушном шаре.
— Спасибо, сэр! — и летят вверх. Холмс задумчиво говорит:
— Интересная местность, Ватсон! Программист пасет коров!
— Холмс, а с чего вы взяли, что он программист?
— Это элементарно! Во-первых, он долго думал над ответом. Во-вторых, его
ответ был абсолютно точен. И в третьих — абсолютно бесполезен!
Теперь все знают что stash — это прятать, но до сих пор не ясно, почему прятать все сразу это «правильно смотреть на стэш», а прятать по частям — неправильно.
Ну почему же бесполезнен, ответ помогает понять почему стэш работает именно так как написано в документации. Это скорее был ответ на вот это:
> Почему нельзя просто добавить в stash только те, которые готовы к коммиту?
С флагом --keep-index — в стэш уйдут все изменения кроме тех что уже добавлены в индекс(подготовлены для комита). Если нужно так же добавить в стэш untracked файлы, то надо указать --include-untracked.
Если делать руками, то можно создать отдельную ветку и туда сохранять что нужно, а потом просто делать git cherry-pick нужного комита, но это немного не удобно и требует больше телодвижений.
Очень верное, ожидаемое замечание. Действительно, теоретически все должно быть так, как Вы сказали — с этим флагом в stash должны уходить только not staged for commit. Но вот незадача, на практике уходят все, кроме untracked.
vim a.txt
git add a.txt
git stash --keep-index
git stash show
a.txt | 1 +
1 file changed, 1 insertion(+)
Т.е. вновь созданный a.txt добавлен в индекс и он же попадает в стэш, что противоречит Вашему утверждению «кроме тех, что уже добавлены в индекс». Поправьте, если ошибаюсь.
Собрал вашу версию:
vovkab@genx ~/test/test $ git version
git version 1.7.10.4
vovkab@genx ~/test/test $ touch a.txt
vovkab@genx ~/test/test $ git add a.txt
vovkab@genx ~/test/test $ git stash --keep-index
Saved working directory and index state WIP on master: b196e9f init
HEAD is now at b196e9f init
vovkab@genx ~/test/test $ git status
# On branch master
# Changes to be committed:
# (use «git reset HEAD ...» to unstage)
#
# new file: a.txt
#
Тоже все нормально. Может с конфигом что то? Хотя я не припомню ключей для stash.
Из того, что Вы привели собственно ничего не следует. Видно что Вы сделали стэш, а потом видно, что файл все еще в индексе. Это ничего не говорит о том, попал ли он в стэш или нет. То что он в индексе после стэш, это правильно. Чтобы его там не оставлять нужен флаг --no-keep-index, но мы же не об этом. Гораздно интереснее увидеть Ваш stash show.
Думал не нужно будет приводить :) Потому что, изменения или остаются или попадают в стэш.
Одни и теже изменения не могут быть одновременно и там и там.
Так или иначе вот:
vovkab@genx ~/test/test $ git stash list
stash@{0}: WIP on master: b196e9f init
vovkab@genx ~/test/test $ git stash show
0 files changed
Tаки я его победил засранца!) Уже искал подходящую прогу для скринкастов, чтобы можно было выложить видео на ютуб, где видно, что я не идиот) Я так понимаю, файлы у Вас пустые? Просто touch a.txt, без информации? Попробуйте не создавать пустышку, а скопировать в папку какой-нибудь файл с данными.
Да вы правы, теперь получилось повторить. Тогда, то что выше написал про изменения не верно.
Прочитав документации еще раз внимательно, в самом начале написано:
Save your local modifications to a new stash, and run git reset --hard to revert them
То есть, так или иначе сохраняется все дерево изменений, но есть возможность не чистить текущее состояние, например индекса и так же спрятать untracked файлы.
Но по сути получается, если вы закомитите изменения в индексе, то после стэша применятся только те которые были unstaged.
А если после стэша, отменить изменения в индексе, то применив стэш, они все восстановятся, и это то как раз чего вам не нужно, если я правильно понимаю?
Возможно стэш используется не совсем по назначению, а именно для создания и редактирования комитов/патчей. Для этого обычно используются ветки.
Я бы предложил сделать бранч, коммитить туда, а потом при необходимости слить коммиты в один более осмысленный. Если вам нужно отложить часть файлов в сторону, сделайте это на другом бранче просто. Потом сможете подмёрджить или черри-пикнуть.
Собственно, в этом и заключается Git way: коммит, коммит и ещё раз коммит.
А вот на вопрос
Почему нельзя просто добавить в stash только те, которые готовы к коммиту?
вам тут, конечно, вряд ли ответят ;) Можно попробовать спросить в гитовой рассылке или IRC: git-scm.com/community
Спасибо. Просто интересовало, если можно так сделать — убрать в stash конкретную часть файлов. Ответ — нельзя. Деваться некуда, теперь буду делать правильно, буду черри-пукать…
Ну да, добавить в stash только выбранные файлы не получится если не читать документацию и не найти команду
git stash push -- [filename]
P.S. Сам факт того, что вам понадобилось припрятать только часть файлов говорит о том, что вы собираетесь сделать хороший и понятный коммит и не желаете попадания в него нежелательных изменений. Мне кажется, что это наоборот свидетельствует о правильном использовании гита, а не о неправильном.
Если нужно в stash Закинуть много файлов, а оставить только несколько то можно пойти по такому пути:
Сначала закидываем все в stash - git stash save "Comment" -u
Потом достаем из stash нужные файлы - git checkout stash@{0} -- path/to/file.ext
Сам искал как добавлять не все файлы, но пришел пока только к такому варианту. Пока он подходит, может и другим поможет.