Когда Сэм ответил , вы хотите использовать опцию --index
. Хотя полезно понять, что происходит внутри.
Когда вы делаете тайник - с git stash save
или более новым глаголом, git stash push
1 -Git фактически выписывает два коммита. Это потому, что коммит является основной единицей хранения Git. 2 Причина, по которой два из них, заключается в том, что один из них хранит то, что находится в index Gitа другие хранят то, что находится в вашем рабочем дереве .
Вы выполняете свою работу - просматриваете и редактируете свои файлы - с обычными файлами, которые вы можете просматривать и редактировать. Они находятся в вашем рабочем дереве (также называется рабочее дерево или любое количество похожих слов и фраз; старая версия Git также использовала фразу рабочий каталог или рабочий каталог ). Это все довольно просто, потому что все инструменты и программы вашего компьютера могут работать с этими файлами.
Но Git не делает коммиты из рабочего дерева. Git делает новые коммиты из index . Индекс настолько важен (и / или так плохо назван), что в Git он имеет три имени: Git иногда называет его «индексом», как этот, но иногда называет его промежуточной областью , а иногда - редков наши дни - называет это кеш . Вы уже знакомы с идеей использования его для создания обновленных файлов;отсюда и название область подготовки . Но на самом деле индекс содержит копию 3 из каждого файла, который будет добавлен в ваш следующий коммит. Эта копия начинается так же, как в текущем коммите, и когда вы обновляете файлы и git add
их, индексная копия заменяется обновленным файлом.
Другими словами,индекс содержит то, что вы предложили сделать следующий коммит. Запуск git add
обновляет этот предложенный следующий коммит. Чтобы сказать вам, чем отличается между вашим текущим коммитом и вашим предлагаемым следующим коммитом, git status
просто сравнивает файлы в текущем коммите с файлами в индексе. Когда они одинаковы, они ничего не говорят, а когда они разные, они говорят «готовятся к коммиту».
Итак: когда вы запускаете git stash save
или git stash push
, Git сначала делает коммит изиндекс, так же, как он может сделать любой коммит из индекса. Затем stash-код создает временный индекс - копируя обычный / реальный - и git add
s все файлы из рабочего дерева во временный индекс, например git add -u
. Затем он делает коммит из этого временного индекса, который соответствует вашему рабочему дереву.
Отсюда и два коммита. Все тайники имеют как минимум эти два коммита. Если вы создаете тайник с флагом -u
или -a
, это добавляет третий коммит ... который становится грязным, поэтому давайте просто предположим, что вы никогда этого не сделаете.
Когда вы применяете или pop a stash - pop
просто означает apply
затем drop
- в этот момент вы выбираете, использовать ли первый коммит stash с содержимым индекса или нет. Если вы используете флаг --index
, Git попытается применить фиксацию индекса к вашему текущему индексу. Это, по сути, запускает операцию git diff
, переданную по каналу git apply --cached
(это гораздо легче увидеть в старом сценарии оболочки git stash
, который буквально выполнялся git diff-tree --binary $s^2^..$s^2 | git apply --cached
).
Если вы не't используйте опцию --index
, git stash apply
просто игнорирует спрятанный индекс! Он просто выполняет оставшуюся часть git stash apply
, то есть запускает git merge-recursive
4 непосредственно на трех коммитах, необходимых для объединения спрятанного рабочего дерева с вашим текущим рабочим деревом. Если этот шаг завершится успешно, git stash pop
сделает сброс тайник, что очень затрудняет восстановление индекса.
Я обычно рекомендую избегать git stash
полностью, 5 но если вы используете его, я рекомендую избегать git stash pop
. Легко забыть флаг --index
. Если вы использовали git stash apply
, у вас все еще есть тайник, и вы можете сбросить настройки (см. Сноску 4) и повторить попытку с помощью --index
.
1 Tон save
глагол был единственным доступным до Git 2.13. В этой версии Git добавлен глагол push
, позволяющий использовать несколько дополнительных опций.
2 Существует внутренняя единица хранения меньшего размера, называемая blob ,но он не подходит для тайников: вам нужно много больших двоичных объектов с именами, хранящимися во внутренних объектах Git tree , и чтобы собрать их все вместе, вам нужен объект commit , поэтомуcommit - это основная единица хранения в Git.
3 Технически, индекс содержит ссылки на внутренние объекты BLOB-объектов , упомянутые в сноске. 2. Эти объекты BLOB-объектов хранят данные файлов в сжатом, доступном только для чтения формате, который Git использует, чтобы файлы были небольшими и готовыми для совместного использования. Поскольку они предназначены только для чтения, скажем, копия, скажем, README.md
, которая находится в десятках или сотнях коммитов, может быть совместно используемой , когда это такая же копия. Индекс также может поделиться им. Запись нового файла в индекс с git add
на самом деле просто сжимает содержимое файла в формат BLOB-объектов. Это автоматически разделяет любую существующую копию файла или создает новый BLOB-объект, если необходимо.
4 Вы, вероятно, никогда не должны запускать git merge-recursive
самостоятельно, так как он обходит "все безопасно передано"" проверить. Эта проверка гарантирует, что в случае неудачного слияния вы можете восстановить с помощью git reset --hard
. Код git stash
обходит эту проверку и, следовательно, может сделать невозможным восстановление после попытки применить тайник. Поэтому хорошая идея, если вы вообще используете git stash
, чтобы убедиться, что git status
говорит, что сначала все чисто.
5 Я все еще использую его сам, но оченьредко и только если я уверен, что это сработает. Даже тогда я могу случайно сжечь себя.