Хранение только не поэтапных изменений в Git

230

Я хотел бы сделать следующий рабочий процесс:

  1. Добавить изменения на сцену.
  2. Спрятать все остальные изменения, которые не были поставлены.
  3. Делайте что-нибудь с вещами на стадии (например, сборка, запуск тестов и т. Д.)
  4. Примените тайник.

Есть ли способ сделать шаг 2?

пример

 echo "123" > foo
 git add foo # Assumes this is a git directory
 echo "456" >> foo
 git stash
 cat foo # Should yield 123
Unapiedra
источник
Почему бы не зафиксировать свои изменения после их постановки?
Shizzmo
3
IIRC --keepindex делает именно это
сех
4
Потому что, если, скажем, сборка не удалась, я не хочу делать это. Я знаю, что могу удалить коммит, но я бы хотел сделать это без коммита, если это возможно.
Унапьедра
Сехе, спасибо. Я могу подтвердить это работает. Ну и дела, я посмотрел руководство по linux.die.net/man/1/git-stash, которое устарело. man git stashгораздо лучше.
Унапьедра
это --keep-index, fwiw.
jaf0

Ответы:

289

git stash saveесть опция, --keep-indexкоторая делает именно то, что вам нужно.

Итак, беги git stash save --keep-index.

vhallac
источник
9
Правда. Я продолжаю использовать saveс git stash. Возможно, это программист, который настаивает на соблюдении симметрии с помощью apply / pop. :)
vhallac
105
Примечание: это все еще хранит все ваши изменения; единственное отличие от обычного git stash saveсостоит в том, что он оставляет уже готовые изменения в вашей рабочей копии. В рабочем процессе выше это будет работать нормально, так как вы просто применяете тайник поверх локальной копии, в которой уже есть половина изменений в тайнике (этот мерзавец достаточно умен, чтобы его игнорировать). Но если вы отредактируете код перед повторным применением тайника, вы можете столкнуться с конфликтами слияния при переходе к применению. Fyi.
peterflynn
2
@ytpete Это укусило меня так много раз. Мне бы очень хотелось, чтобы у git был способ хранить только те вещи, которые вы не храните ... Я часто совершаю какие-то действия, затем делаю полный git stash, зная, что могу, git commit --ammendесли возникнут проблемы в том, что я совершил.
rjmunro
1
--amend(а не --ammend)
Rhubbarb
19
Это решение не работает для меня из-за проблем, описанных peterflynn. Это не очень хороший ответ на вопрос, так как он все еще хранит поэтапные изменения. У кого-нибудь есть лучшее решение?
user643011
43

Это можно сделать за 3 шага: сохранить поэтапные изменения, спрятать все остальное, восстановить индекс с поэтапными изменениями. Что в основном:

git commit -m 'Save index'
git stash push -u -m 'Unstaged changes and untracked files'
git reset --soft HEAD^

Это будет делать именно то, что вы хотите.

alesguzik
источник
3
Примечание: -uтакже хранит неотслеживаемые файлы.
ma11hew28
Этот подход по сути дублирует то, что git stash save --keep-indexделает с гораздо большей работой. Я не вижу никаких преимуществ.
Иниго
1
@vas Нет, подход не дублирует это. Смотрите комментарий peterflynn к принятому ответу.
Александр Клауэр
28
git stash save --keep-index

Также Re:

Почему бы не зафиксировать свои изменения после их постановки? - Шин

A: Потому что вы всегда должны проверять проверенный код :) Это означает, что вам нужно запускать тесты только с теми изменениями, которые вы собираетесь зафиксировать

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

sehe
источник
14

С git version 2.7.4вами можно сделать:

git stash save --patch

gitПопросит вас добавить или нет изменений в притон.
А ты тогда просто ответь yилиn

Вы можете восстановить рабочий каталог, как вы всегда это делаете:

git stash pop

или, если вы хотите сохранить сохраненные изменения в тайнике:

git stash apply
Евгений Коньков
источник
Это круто. Это немного трудоемко, но, по крайней мере, вы можете пропустить и добавить целые файлы.
Дастин Опря
5

Расширяя предыдущие ответы, я иногда делаю сложный набор изменений, но сначала хочу зафиксировать отдельное изменение. Например, я мог заметить ошибку или другой неправильный код, который я хотел бы исправить перед своими поэтапными изменениями. Один из возможных маршрутов:

сначала спрятать все, но оставить инсценированные изменения без изменений

$ git stash save --keep-index [--include-unraracked]

спрятать поэтапные изменения тоже отдельно

$ git stash save

внести изменения для исправления; и тестирование; совершить их:

$ git add [--interactive] [--patch]

$ git commit -m "fix ..."

Теперь восстановим ранее поставленные изменения:

$ git stash pop

разрешите все конфликты и обратите внимание, что если бы были конфликты, git применил, но не удалил эту запись верхнего тайма.

(... Затем зафиксируйте поэтапные изменения, восстановите тайник всех остальных изменений и продолжите ...)

Rhubbarb
источник
4

Чтобы добавить неразмеченные (не добавленные для фиксации) файлы в stash, выполните следующую команду:

git stash -k

Затем вы можете зафиксировать поставленные файлы. После этого вы можете вернуть последние сохраненные файлы с помощью команды:

git stash pop
srth12
источник
4

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

Этот псевдоним работает хорошо:

stash-working = "!f() { \
  git commit --quiet -m \"temp for stash-working\" && \
  git stash push \"$@\" && \
  git reset --quiet --soft HEAD~1; }; f"

Он временно фиксирует поэтапные изменения, создает тайник из оставшихся изменений (и позволяет передавать дополнительные аргументы, такие как --include-untrackedи, --messageв качестве аргументов псевдонима), а затем сбрасывает временную фиксацию для возврата поэтапных изменений.

Это похоже на @Simon Кнапп ответ , но с некоторыми незначительными отличиями - он использует --quietна временных мерах , принятых, и он принимает любое количество параметров для тайника push, а не жесткого кодирования -m, и он добавляет --softк финалу сбросить, чтобы индекс остался таким же, как и начался.

Для противоположной проблемы хранения только поэтапных изменений (псевдоним stash-index) см. Этот ответ .

Раман
источник
2

Еще один совет, связанный с вопросом:

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

$ git stash save --keep-index

Возможно, вы захотите дать тайнику сообщение, так что когда вы делаете git stash listэто, становится более очевидным, что вы спрятали ранее, особенно если вы выполняете эту операцию при дальнейшем сохранении. Например

$ git stash save --keep-index "изменения еще не внесены"

(хотя на самом деле он содержит все изменения, как отмечено в других ответах).

Например, вышеизложенное может сразу сопровождаться:

$ git stash save "поэтапные изменения для функции X"

Остерегайтесь, однако, что вы не можете затем использовать

$ git stash apply "stash @ {1}" ### ✘ не совсем делает то, что вы хотите

восстановить только неустановленные изменения.

Rhubbarb
источник
2

У Git нет команды, которая хранит только ваши неустановленные изменения.

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

git stash push --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

Если вы хотите сохранить только определенные изменения в этих файлах, добавьте эту --patchопцию.

git stash push --patch --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

--include-untrackedОпция позволяет копить неотслеживаемые файлы.

git stash push --include-untracked --message 'Untracked files' -- app/controllers/widgets_controller.rb test/controllers/widgets_controller_test.rb

Запустите git help stash(или man git-stash) для получения дополнительной информации.

Примечание. Если ваши неустановленные изменения довольно дезогенизированы, ответ @ alesguzik, вероятно, будет проще.

ma11hew28
источник
0

Современная форма этой команды git stash push [--] [<pathspec>...], так как Git 2.16+ ( git stash saveустарела )

Вы можете комбинировать это с подстановочной формой, например:

git stash push --all --keep-index ':(glob)**/*.testextension' 

Но это не работает с Git для Windows, пока Git 2.22 (Q2 2019), см. Выпуск 2037 , учитывая, что git stashон был повторно реализован в C (вместо сценария оболочки)

См. Коммит 7db9302 (11 марта 2019 г.) Томаса Гуммерера ( tgummerer) .
См. Коммит 1366c78 , коммит 7b556aa (07 марта 2019 г.) Йоханнеса Шинделина ( dscho) .
(Слиты Junio C Hamano - gitster- в фиксации 0ba1ba4 , 22 Apr 2019)

встроенный stash: :(glob)снова обрабатывать pathspecs

При передаче списка спецификаций пути, скажем, git addнам нужно быть осторожными, чтобы использовать исходную форму, а не проанализированную форму спецификаций пути.

Это имеет значение, например, при звонке

git stash -- ':(glob)**/*.txt'

где исходная форма содержит :(glob)префикс, а проанализированная форма - нет.

Однако во встроенной git stashмы передали проанализированную (то есть неправильную) форму и git addпотерпели неудачу с сообщением об ошибке:

fatal: pathspec '**/*.txt' did not match any files

на этапе, где git stashудаляются изменения из рабочего дерева, даже если refs/stashоно действительно было успешно обновлено.

VonC
источник
0

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

mystash = "!f() { git commit -m hold && git stash push -m \"$1\" && git reset HEAD^; }; f"

Который:

  • фиксирует все в индексе,
  • хранит то, что изменилось в рабочем дереве (может, конечно, добавить -uили -a),
  • сбрасывает последний коммит обратно в рабочую попытку (возможно, захотите использовать, --softчтобы сохранить его в индексе).
Саймон Кнапп
источник