Чому не можна застосовувати схованку до робочого каталогу?


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
@ Мігель: Заховання не є перешкодою. Це додатковий інструмент, наданий Git, який дозволяє покращити робочий процес та уникнути конфліктів та нечистих комітів. git-scm.com/docs/git-stash
Koraktor

8
Поки відповідь вірна, я справді не впевнений, що git "правильний" щодо цього. Файли знаходяться в репозиторії, тому немає загрози втрати даних. чому б просто не застосувати зміни? Дивіться цю тему - git.661346.n2.nabble.com/stash-refuses-to-pop-td7453780.html
studgeek

5
Я вважаю, що ця відповідь не найкорисніша. git stashмає допомогти швидко зробити резервну копію локальних змін. Видалення набору файлів вручну для його відновлення порушує процес. git stash branchПідхід в іншу відповідь звучить краще, але все ж набагато більш ручний , ніж хотілося б .
бентолор

Ця відповідь найкраще спрацювала для мене, коли потрапила в ту ж ситуацію. Після того, як я вибив схованку, я пройшов об'єднання, як я очікував з самого початку.
Біллі Лаццаро,

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.
Hilbrand Bouwkamp

2
Насправді popце поєднання applyі drop, але буде, лише dropякщо applyпрацювали без конфліктів. Але так, applyзазвичай безпечніше.
Koraktor

2
Це передбачає відсутність інших змін у робочому каталозі, які ви хочете зберегти. Для цього конкретного питання він натякає (але прямо не говорить), що він перебуває в чистому стані, але я хотів зазначити, що для інших, які приїжджають сюди із місцевими змінами.
studgeek

1
Це вирішує проблему, лише якщо конфліктні проблеми не були допущені . Ви отримуєте точно таке саме повідомлення, коли вони були скоєні (наприклад, при чистому оформленні замовлення), і тоді це нічого не змінить ...
Джаспер

56

Як згадував @bentolo, ви можете вручну видалити файли, на які він скаржиться, змінити гілки, а потім вручну додати їх назад. Але я особисто вважаю за краще залишатися "в межах git".

Найкращий спосіб зробити це - перетворити схованку на гілку. Коли це гілка, ви можете нормально працювати в git, використовуючи звичайні техніки / інструменти, пов'язані з гілками, які ви знаєте і любите. Це насправді корисна загальна техніка роботи зі схованками, навіть коли у вас немає переліченої помилки. Це добре працює, тому що схованка справді є комітом під ковдрами (див. PS).

Перетворення схованки на гілку

Далі створюється гілка на основі HEAD, коли було створено схованку, а потім застосовується схована (вона не фіксується).

git stash branch STASHBRANCH

Робота з "схованкою"

Що робити далі, залежить від взаємозв'язку між схованкою та місцем знаходження вашої цільової гілки (яку я буду називати ORIGINALBRANCH).

Варіант 1 - Знову перебазувати гілку схованки (багато змін після схованки)

Якщо ви зробили багато змін у своєму ОРИГІНАЛЬНОМУ ФІЛІЇ, то вам, мабуть, найкраще ставитися до STASHBRANCH, як до будь-якого місцевого відділення. Зафіксуйте свої зміни в STASHBRANCH, перебазуйте їх на ORIGINALBRANCH, а потім перейдіть на ORIGINALBRANCH і перебазуйте / об'єднайте зміни STASHBRANCH над ним. Якщо є конфлікти, тоді обробляйте їх нормально (одна з переваг цього підходу полягає в тому, що ви можете бачити та вирішувати конфлікти).

Варіант 2 - Скинути оригінальну гілку, щоб вона відповідала схованці (обмежені зміни після схованки)

Якщо ви просто сховали, зберігаючи деякі поетапні зміни, а потім здійснили, і все, що ви хочете зробити, - це отримати додаткові зміни, які, якщо вони не були виконані під час сховання, ви можете зробити наступне. Він повернеться до початкової гілки та індексу без зміни робочої копії. Кінцевим результатом будуть ваші додаткові схованки у вашій робочій копії.

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

Фон

Зберігання - це коміти, як гілки / теги (не патчі)

PS, спокусливо думати про схованку як про патч (так само, як спокусливо думати про коміт як про патч), але схованка насправді є комітом проти HEAD, коли вона була створена. Коли ви подаєте заявку / поп, ви робите щось подібне до збору вишні у вашій поточній гілці. Майте на увазі, що гілки та теги насправді є лише посиланнями на коміти, тому багато в чому схованки, гілки та теги - це просто різні способи вказівки на коміт (та його історію).

Іноді це потрібно навіть тоді, коли ви не вносили змін до робочого каталогу

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


5
Цю відповідь слід позначити як рішення, оскільки вона надає найбільш корисні вказівки щодо того, як найефективніше вирішити "заблокований тайник". Можливо, покращити його, згадавши спочатку `` просте рішення видалення '', а рішення про розгалуження - другий варіант.
бентолор

8
"git stash branch STASHBRANCH", здається, не працює, якщо ви стикаєтесь із цим сценарієм (трапляється абсолютно те саме повідомлення про помилку, що і при pop). Можливо, вам доведеться зробити деякі скидання Git заздалегідь.

+1 Я потрапив у безлад у спагетті з комітами, змінами, зберіганням тощо, і т. Д. Це витягнуло мене, вивісивши схованку до філії завдяки studgeek
RobbZ

Дякуємо за роз'яснення щодо того, як схованки не є патчами та як вони прив'язані до ГОЛОВИ (під час сховання). Це має багато сенсу. - Отже ... Я припускаю, що бувають випадки, коли гнучкіше / портативніше / зручніше створювати патч, а не схованку (як ви вже згадували: при великій кількості змін), щоб його можна було застосувати де завгодно (і це просто питання вирішення конфліктів). Можливо git stash show -p, допомагає там робити схованку -> * патч *.
Kamafeather

39

Рішення: Вам потрібно видалити відповідний файл, а потім спробуйте знову сховати / застосувати, і він повинен пройти. Не видаляйте інші файли, лише ті, що згадуються в помилці.

Проблема: Git іноді смокче. При запуску git stash -uвін включає файли, що не відстежуються (круто!), Але він не видаляє ці файли, що не відстежуються, і не знає, як застосувати сховані файли, що не відстежуються, над залишками (не круто!), Що насправді робить цю -uопцію досить марною.


3
Я б прийняв цю відповідь, якби це було моє запитання. Дякую @qwertzguy, ваша відповідь вирішила мою проблему,
Kobus Myburgh

Я сам зіткнувся з тим самим питанням, git stash pop не застосовувався, поки я не видалив відповідні файли - тоді я зіткнувся з конфліктом із файлом, який спричинив відхилення сховища. Але замість того, щоб видалити невідстежені файли, вони залишили їх за собою. Тож зверніть увагу на те, що майбутнє не триматися подаліgit stash -u
notzippy

Погана порада, якщо вам потрібні частини обох версій файлів, на які це впливає.
Уолф

2
"він не видаляє ці файли, що не відстежуються" ... і не вносить їх у список git stash show. Ця відповідь змусила лампочку продовжувати працювати.
АТ

2
плюс один для Git іноді відстій.
Харіш

29

Щоб застосувати відмінності коду в схованці як патч, скористайтеся наступною командою:

git stash show --patch | patch -p1

11
Зазвичай краще пояснити рішення, а не просто публікувати кілька рядків анонімного коду. Ви можете прочитати Як написати хорошу відповідь , а також пояснити цілком відповіді на основі коду .
Massimiliano Kraus

Це працює для мене, оскільки виправлення з 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

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

Подробиці: я використовував git stash save -a, перевіряв майстер, щоб скомпілювати та побачити оригінальну поведінку, а потім спробував повернути все, щоб продовжувати редагування. Коли я перевірив свою гілку і спробував вискочити, мої проігноровані файли все ще були там до збереження схованки. Це пов’язано з тим, що перевірка майстра впливала лише на зафіксовані файли - ігноровані файли не видалялися. Тож поп не вдався, по суті заявивши, що не хоче відновлювати мої сховані ігноровані файли поверх файлів, які все ще там були. Шкода, що я не зміг знайти спосіб розпочати сеанс злиття з ними.

Зрештою, я раніше git clean -f -d -xвидаляв проігноровані файли. Цікаво, що з моїх ~ 30, 4 файли все ще залишились після очищення (поховані в підкаталогах). Мені доведеться з’ясувати, в якій вони категорії, що їх потрібно було видалити вручну.

Тоді мій поп досяг успіху.



-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 року вам потрібно було видалити відповідний файл, а потім спробувати знову сховати / застосувати.
З наступним випуском Git вам не доведеться цього робити.

Див. Комітет bbffd87 (11 серпня 2017 р.) Ніколя Морі-Шайзамартіна ( nmorey) .
(Об’єднано Junio ​​C Hamano - gitster- у комітеті 0ca2f32 , 23 серпня 2017 р.)

stash: очистити невідстежені файли перед скиданням

Якщо виклик git stash -uрепозиторію, що містить файл, який більше не ігнорується через поточну модифікацію gitignoreфайлу, цей файл зберігається, але не видаляється з робочого дерева.
Це пов’язано із тим, що git-stashспочатку виконується a, reset --hardщо очищає .gitignoreмодифікацію файлу, а потім викликається git clean, залишаючи файл недоторканим.
Це спричиняє git stash popпомилку через наявний файл .

Цей патч просто перемикає порядок між очищенням та скиданням і додає тест для цього випадку використання.


-1

Найбезпечніший спосіб стеження за схованкою

git stash -u

Це збереже всі, включаючи нестандартні зміни

git stash drop

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


Як пояснено в stackoverflow.com/a/23743125/6309 , це не завжди буде працювати з Git 2.14 або менше. Вона буде працювати з Git 2.15: stackoverflow.com/a/46027357/6309
VonC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.