Почему нельзя применить stash к рабочему каталогу?

96

Я не могу вернуть тайник в рабочий каталог.

Маленькая история:

Сначала я попытался протолкнуть некоторые зафиксированные изменения, но он сказал: «Нет, вы не можете, сначала потяните» ... Хорошо, тогда я извлечу что-то из GitHub, а затем отправлю свои изменения. Когда я попытался вытащить, он сказал, что у меня есть изменения, которые будут перезаписаны, и что я должен спрятать свои изменения. Хорошо, я спрятал изменения ... потянул и подтолкнул зафиксированные изменения. Но теперь я не могу восстановить незафиксированные изменения, над которыми работал.

Это ошибка:

MyPath/File.cs already exists, no checkout
Could not restore untracked files from stash

Наверняка я еще не понимаю всех концепций git, они меня немного смущают ... может я что-то сделал не так.

Было бы здорово, если бы кто-нибудь помог мне решить эту проблему ... Я искал в Google и все остальное уже больше часа, и я еще не нашел решения.

Помощь очень ценится. Спасибо!

Мигель Анджело
источник

Ответы:

74

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

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

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

  1. перемести это в другое место
  2. применить тайник
  3. вручную объединить две версии файла (рабочее дерево или перемещенное).
бладибла
источник
2
Есть ли способ избежать необходимости прятать что-то в будущем ... Я пришел из SVN, и он с нетерпением ждет ... вы просто обновляете, разрешаете конфликты, а затем фиксируете. Git не может быть настолько сложным, что мне нужно добавить 2 шага в цикл. Еще раз спасибо!
Мигель Анджело
2
@Miguel: Тайники не помеха. Это дополнительный инструмент, предоставляемый Git, который позволяет улучшить рабочий процесс и избежать конфликтов и нечистых коммитов. git-scm.com/docs/git-stash
Koraktor
8
Хотя ответ верен, я действительно не уверен, что git "правильный" в этом отношении. Файлы находятся в репо, поэтому нет опасности потери данных. почему бы просто не применить изменения? См. Эту ветку
studgeek
5
Думаю, этот ответ не самый полезный. git stashдолжен помочь быстро сделать резервную копию локальных изменений. Удаление набора файлов вручную для его восстановления прерывает поток. git stash branchПодход в другой ответ звучит лучше, но все же гораздо более ручной , чем хотелось бы .
bentolor
Этот ответ сработал для меня лучше всего в той же ситуации. После того, как я открыл тайник, я провел слияние, как я и ожидал с самого начала.
Billy Lazzaro
58

Самый безопасный и простой способ - это снова спрятать вещи:

git stash -u             # This will stash everything, including unstaged files
git stash pop stash@{1}  # This will apply your original stash

Впоследствии, если результат вас устраивает, вы можете позвонить

git stash drop

чтобы убрать ваш «безопасный» тайник.

Корактор
источник
2
Спасибо за это, избавил меня от множества боли и страданий!
danjarvis
9
stash pop применится и сбросит ваш исходный тайник. На всякий случай используйте applyвместо pop.
Хильбранд Боукамп,
2
Фактически popявляется комбинацией applyи drop, но будет только в том dropслучае, если applyсработало без конфликтов. Но да, applyобычно безопаснее.
Koraktor
2
Это предполагает, что в рабочем каталоге нет других изменений, которые вы хотите сохранить. В отношении этого конкретного вопроса он подразумевает (но не говорит явно), что находится в чистом состоянии, но я хотел указать на это другим, приходящим сюда с локальными изменениями.
Studgeek
1
Это решает проблему только в том случае, если конфликтующие проблемы не были зафиксированы . Вы получите точно такое же сообщение, когда они были зафиксированы (например, при чистой проверке), и тогда это ничего не изменит ...
Джаспер
56

Как упоминалось @bentolo, вы можете вручную удалить файлы, на которые он жалуется, переключить ветки, а затем вручную добавить их обратно. Но лично я предпочитаю оставаться «в рамках мерзавца».

Лучший способ сделать это - преобразовать тайник в ветку. Когда это ветвь, вы можете нормально работать в git, используя обычные методы / инструменты, связанные с ветвями, которые вы знаете и любите. На самом деле это полезный общий метод работы с тайниками, даже если у вас нет указанной ошибки. Это хорошо работает, потому что тайник - это действительно скрытая фиксация (см. PS).

Преобразование тайника в ветку

Следующее создает ветку на основе HEAD при создании тайника, а затем применяет тайник (он не фиксирует его).

git stash branch STASHBRANCH

Работа с "веткой тайника"

Что вы будете делать дальше, зависит от отношения между тайником и местом, где сейчас находится ваша целевая ветка (которую я назову ORIGINALBRANCH).

Вариант 1 - переустановить ветку тайника в обычном режиме (много изменений с момента тайника)

Если вы внесли много изменений в свой ORIGINALBRANCH, то вам, вероятно, лучше всего относиться к STASHBRANCH как к любому локальному филиалу. Зафиксируйте свои изменения в STASHBRANCH, переустановите его на ORIGINALBRANCH, затем переключитесь на ORIGINALBRANCH и переустановите / объедините изменения STASHBRANCH поверх него. Если есть конфликты, обработайте их как обычно (одно из преимуществ этого подхода - вы можете видеть и разрешать конфликты).

Вариант 2 - сбросить исходную ветку, чтобы она соответствовала тайнику (ограниченные изменения с момента тайника)

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

git symbolic-ref HEAD refs/heads/ORIGINALBRANCH
git reset

Задний план

Тайники - это ветки / теги лайков (не патчи)

PS Заманчиво думать о тайнике как о патче (точно так же, как заманчиво думать о фиксации как о патче), но на самом деле тайник - это фиксация против HEAD, когда он был создан. Когда вы применяете / pop, вы делаете что-то похожее на выбор вишни в текущей ветке. Имейте в виду, что ветки и теги на самом деле являются просто ссылками на коммиты, поэтому во многих случаях тайники, ветки и теги - это просто разные способы указания на коммит (и его историю).

Иногда требуется, даже если вы не внесли изменений в рабочий каталог

PPS, вам может понадобиться этот метод после того, как вы просто использовали stash с --patch и / или --include-untracked. Даже без изменения рабочих каталогов эти параметры могут иногда создавать тайник, который вы не можете просто применить обратно. Должен признаться, не совсем понимаю почему. См. Http://git.661346.n2.nabble.com/stash-refuses-to-pop-td7453780.html для обсуждения.

Studgeek
источник
5
Этот ответ следует пометить как решение, поскольку он дает наиболее полезные указания о том, как наиболее эффективно разрешить «заблокированный тайник». Возможно, улучшите его, упомянув сначала «простое решение для удаления», а во втором - решение для веток.
bentolor 04
8
"git stash branch STASHBRANCH", похоже, не работает, если вы столкнулись с этим сценарием (появляется точно такое же сообщение об ошибке, как и с pop). Возможно, вам придется заранее выполнить некоторые сбросы git.
+1 я выбрался в спагетти беспорядка с фиксациями и изменениями и припрятать и т.д. и т.п. Это заставило меня из него внезапных копить на ветку спасибо studgeek
RobbZ
Спасибо за пояснение о том, что тайники не являются патчами и как они привязаны к ГОЛОВКЕ (во время хранения). В этом есть смысл. - Итак ... Я полагаю, что есть случаи, когда более гибко / переносимо / удобно создавать патч, а не тайник (как вы упомянули: при большом количестве изменений), чтобы его можно было применять где угодно (и просто вопрос разрешения конфликтов). Может git stash show -pтам помогает сделать stash -> * patch *.
Kamafeather
39

Решение: вам нужно удалить файл, о котором идет речь, затем снова попытаться спрятать pop / apply, и он должен пройти. Не удаляйте другие файлы, только те, которые указаны в ошибке.

Проблема: Git иногда отстой. При запуске git stash -uон включает неотслеживаемые файлы (круто!), Но он не удаляет эти неотслеживаемые файлы и не знает, как применить спрятанные неотслеживаемые файлы поверх остатков (не круто!), Что действительно делает эту -uопцию довольно бесполезной.

qwertzguy
источник
3
Я бы принял этот ответ, если бы это был мой вопрос. Спасибо @qwertzguy, ваш ответ решил мою проблему,
Kobus Myburgh
Я столкнулся с той же проблемой, git stash pop не будет применяться, пока я не удалю файлы, о которых идет речь, - затем я столкнулся с конфликтом с файлом, из-за которого тайник был отклонен. Но вместо того, чтобы удалить неотслеживаемые файлы, они остались позади .. Так что обратите внимание на будущее, держитесь подальше отgit stash -u
notzippy
Плохой совет, если вам нужны части из обеих версий затронутых файлов.
Walf
2
"он не удаляет эти неотслеживаемые файлы" ... и не перечисляет их в git stash show. Этот ответ заставил лампочку загореться.
ао
2
плюс один для Git иногда отстой.
Хариш
29

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

git stash show --patch | patch -p1
шифровальщик
источник
11
Обычно лучше объяснить решение, чем просто опубликовать несколько строк анонимного кода. Вы можете прочитать « Как написать хороший ответ» , а также « Объяснение полностью основанных на коде ответов» .
Массимилиано Краус
Это сработало для меня, так как патч от git stash show --patchне содержит неотслеживаемых файлов.
Стивен Шоу
Этот ответ мне очень помог, так как я не смог открыть свой тайник из-за множества изменений в моем репо, так как тайник был нажат.
Эрик Финнман
1

Это случалось со мной много раз, я прячу неотслеживаемые файлы с git stash -u которые в конечном итоге добавляются в репо, и я больше не могу применять спрятанные изменения.

Мне не удалось найти способ принудительно git stash pop/applyзаменить файлы, поэтому я сначала удаляю локальные копии неотслеживаемых файлов, которые были спрятаны ( будьте осторожны, так как это удалит все изменения, которые не были зафиксированы ), а затем применяю спрятанные изменения :

rm `git ls-tree -r stash@{0}^3 --name-only`
git stash apply

Наконец, я использую git status, git diffи другие инструменты для проверки и добавить обратно часть из удаленных файлов , если есть что - то отсутствует.


Если у вас есть незафиксированные изменения, которые вы хотите сохранить, вы можете сначала создать временную фиксацию:

git add --all
git commit -m "dummy"
rm `git ls-tree -r stash@{0}^3 --name-only`
git stash apply

Используйте любые инструменты, которые вам подходят, чтобы объединить ранее зафиксированные изменения обратно в локальные файлы и удалить фиктивную фиксацию:

git reset HEAD~1
Хелдер Перейра
источник
0

Моя аналогичная заблокированная операция всплывающего окна была вызвана тем, что оставшиеся проигнорированы файлы (см. Файл .gitignore). Статус Git показал, что я отслеживаю и не отслеживаю, но мои действия не очищали игнорируемые файлы.

Детали: я использовалgit stash save -a , проверил мастер, чтобы скомпилировать и увидеть исходное поведение, затем попытался вернуть все обратно, чтобы продолжить редактирование. Когда я проверил свою ветку и попытался открыть, мои проигнорированные файлы все еще были там до сохранения тайника. Это связано с тем, что проверка мастера затрагивает только зафиксированные файлы - она ​​не стирает игнорируемые файлы. Таким образом, pop не удалось, по сути говоря, что он не хочет восстанавливать мои спрятанные игнорируемые файлы поверх файлов, которые все еще были там. К сожалению, я не смог найти способ начать с ними сеанс слияния.

В конечном итоге я git clean -f -d -xудалял игнорируемые файлы. Интересно, что из моих ~ 30, 4 файла остались после очистки (похоронены в подкаталогах). Мне нужно выяснить, к какой категории они относятся, и что их пришлось удалить вручную.

Тогда мой поп удался.

отменен
источник
0

Попробуй это:

git checkout stash -.

Налан Мадхесваран
источник
-1

Другое решение:

cd to/root/your/project

# Show what git will be remove
git clean -n

# If all is good
git clean -f

# If not all is good, see
git clean --help

# Finish
git stash pop
ктретьяк
источник
Ошибка, упомянутая в вопросе, вызвана файлом, который существует как в стеке, так и в рабочем каталоге. Очистка исправляет это только в том случае, если этот файл не отслеживается, что, конечно, не всегда так (и не в случае OP, поскольку он получил файл в результате извлечения).
Xavier Poinas
-1

С Git 2.14.x / 2.15 (Q3 2017), qwertzguy «s решение с 2014 года не нужно будет больше.

До третьего квартала 2017 года вам нужно было удалить соответствующий файл, а затем снова попытаться сохранить pop / apply.
В следующем выпуске Git вам не придется этого делать.

См. Commit bbffd87 (11 августа 2017 г.) Николас Мори-Шейсемартин ( nmorey) .
(Объединено Junio ​​C Hamano - gitster- в коммите 0ca2f32 , 23 августа 2017 г.)

stash: очистить неотслеживаемые файлы перед сбросом

Если вызывается git stash -uрепо, содержащее файл, который больше не игнорируется из-за текущей модификации gitignoreфайла, этот файл сохраняется, но не удаляется из рабочего дерева.
Это связано с тем, что git-stashсначала выполняется reset --hardоперация, которая очищает .gitignoreмодификацию файла, а затем вызывается git clean, оставляя файл нетронутым.
Это вызывает git stash popсбой из-за наличия файла .

Этот патч просто переключает порядок между очисткой и сбросом и добавляет тест для этого варианта использования.

VonC
источник
-1

Самый безопасный способ спрятать

git stash -u

Это сохранит все, включая неустановленные изменения

git stash drop

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

РахулМохан Колаканды
источник
Как объясняется в stackoverflow.com/a/23743125/6309 , это не всегда будет работать с Git 2.14 или ниже. Он будет работать с Git 2.15: stackoverflow.com/a/46027357/6309
VonC