Почему "git stash apply" меняет свои изменения?
Я делаю изменения, а затем я git stash
, а затем я git stash apply
Мой вопрос
-
почему после я git stash apply
мое изменение становится "поставленным"? то есть я ничего не увижу, если я сделаю git diff
, я вижу только свою разницу, если я делаю git diff --cached
?
-
Есть ли какие-либо "неустановленные" изменения, внесенные командой git stash apply
?
-
Есть ли какая-либо команда git, в основном позволяющая мне сделать резервную копию моего изменения, reset его в HEAD и копию моей резервной копии назад? Я думал, что git stash
, а затем git stash apply
- это команда, но некоторые из них "устроили" все мои изменения? Есть ли какой-либо эквивалент, который позволяет мне git stash apply
без поэтапной части изменений?
Спасибо.
Ответы
Ответ 1
Если вы обнаружите, что ваши изменения неожиданно поставлены, выполните:
git reset HEAD
Обычно я вижу это только в случае конфликта при применении спрятанных изменений. Вам нужно будет проверить, действительно ли это так, прежде чем делать git reset
.
Команда git stash
является наиболее подходящей для вашего случая использования. Я использую его все время для этой цели.
Ответ 2
Почему git stash применяет этап моих изменений?
Все, что повлияет на ваше рабочее дерево (как git checkout -- afile
), сначала повлияет на ваш индекс.
индекс является средним человеком для перемещения вещей из вашего рабочего дерева в хранилище объектов и для перемещения объектов из хранилища объектов в рабочее дерево.
Индекс также используется git stash apply
для записи конфликтов слияния, поскольку индекс содержит записи этапа-n. См. git merge
:
Для конфликтующих путей файл индекса записывает до трех версий:
- Этап 1 хранит версию у общего предка,
- этап 2 от HEAD и
- этап 3 из MERGE_HEAD (вы можете проверить этапы с помощью
git ls-files -u
).
В истории эволюции git stash --apply
следует отметить два интересных события:
В апреле 2011 года (Git 1.7.5.1, commit e0e2a9c), stash
отменил проверку грязной рабочей таблицы.
Перед тем, как применить табуляцию, мы гарантируем, что в рабочей строке нет изменений, которые не указаны в индексе. Эта проверка восходит к исходному git-stash.sh
и, по-видимому, предназначена для предотвращения случайного потери изменений в рабочем дереве во время слияния.
Однако эта проверка имеет две проблемы:
-
Это чрезмерно ограничительный. Если мой штамп меняет только файл "foo
", но "bar
" загрязнен в рабочем дереве, это помешает нам применить кэш.
-
Это избыточно. Мы вообще не касаемся рабочего дерева, пока мы на самом деле не назовем репликацию слияния.
Но у него есть свои (гораздо более точные) проверки, чтобы избежать потери данных рабочего дерева и прервать слияние с более приятным сообщением о том, какие пути были проблемы.
Итак, мы можем просто полностью отбросить чек.
Использование индекса для управления слиянием, выполненным с помощью git stash apply
, приведет к другой ошибке, обнаруженной в апреле 2015 года, git 2.4.2, commit ed178ef:
stash
: требуется использовать чистый индекс
Если вы поставили содержимое в своем индексе и запустили "stash apply
", мы можем столкнуться с конфликтом и вставить новые записи в индекс.
В этом случае трудно восстановить исходное состояние, потому что такие инструменты, как "git reset --keep
", сдуют что-нибудь поэтапно.. Мы можем сделать это более безопасным, отказавшись от применения при поэтапных изменениях.
Ответ 3
Я думаю, что что-то может быть неправильным в вашей конфигурации, так как git stash
записывает состояние индекса и рабочего дерева перед сбросом на последнюю фиксацию, git stash apply
должен только пытаться восстановить состояние индекса, если вы используйте опцию --index
.
Одна из возможных путаниц заключается в том, что если у вас есть конфликт (т.е. возникают конфликты слияния, потому что кошелек применяется к другому комманде, где файлы, затронутые этим типом, были изменены с момента фиксации, при которой был сделан тайник), то, если вы используете mergetool
для разрешения конфликтов, mergetool
автоматически сгенерирует изменения файлов с успешным разрешением.
Как утверждает Грег Хьюглил, простой reset будет нести все поэтапные изменения.
git reset