Git stash: "Неможливо застосувати до брудного робочого дерева. Будь ласка, сформулюйте зміни"


133

Я намагаюся застосувати зміни, з якими я зупинився раніше, git stash popі отримаю повідомлення:

Cannot apply to a dirty working tree, please stage your changes

Будь-яка пропозиція, як з цим боротися?

Відповіді:


196

Коли мені доведеться застосувати сховані зміни до брудної робочої копії, наприклад, вивівши більше одного набору змін зі сховища, я використовую наступне:

$ git stash show -p | git apply -3 && git stash drop

В основному це

  1. створює патч
  2. труби, які відповідають команді застосувати
  3. якщо є якісь конфлікти, їх потрібно буде вирішити за допомогою тристороннього злиття
  4. якщо застосувати (або об'єднати) вдалося, воно скидає щойно застосований прихований елемент ...

Цікаво, чому немає жодного -f(силового) варіанту, git stash popякий би мав би вести себе так, як однолінійний вище.

Тим часом ви можете додати цей однокласник як псевдонім git:

$ git config --global --replace-all alias.unstash \
   '!git stash show -p | git apply -3 && git stash drop'
$ git unstash

Дякуємо @SamHasler за вказівку -3параметра, який дозволяє вирішувати конфлікти безпосередньо за допомогою тристороннього злиття.


Чи git stash show -p | git applyвідрізняється від git stash apply?
Фактор Містик

1
Jo Factor git stash applyне застосує прихованих змін, якщо у вас є брудна робоча копія. Таким чином, ви можете бачити, git stash show -p | git applyяк застосовується якесь примусове сховище.
muhqu

1
не допомагає Але допоможе: git скидає HEAD та видаляє зміни після цього.
Роджер Чужий

4
Я отримую "помилка: патч не вдався ... патч не застосовується" для одного з файлів. Я б хотів, щоб це призвело до конфлікту злиття.
Олександр Дубінський

1
Це рішення не працювало для мене, воно не вдалося error: <file> does not match indexдо кожного зміненого файлу. Однак інше рішення спрацювало.
silvenon

57

Я роблю це таким чином:

git add -A
git stash apply

а потім (необов'язково):

git reset

2
+1! Це простіше, ніж інші рішення, що передбачають генерування виправлень або внесення змін, і вони зберігають ваші локальні зміни безпечно ізольованими від застосованих змін сховища, поки ви не переконаєтесь, що зміни були об’єднані належним чином.
peterflynn

Я отримую помилку "... вже існує, немає замовлення ... Не вдалося відновити незавершені файли із сховища"
Олександр Дубінський

2
Я використовував git add -u, що схоже, -Aза винятком того, що він не додає файли без відстеження.
Бред Купіт

9

Це можна зробити, не зберігаючи поточні зміни, експортувавши потрібну копію у файл патчу та застосувавши її вручну.

Наприклад, скажіть, що ви хочете застосувати скриньку @ {0} до брудного дерева:

  1. Експортуйте скриньку @ {0} як виправлення:

    git stash show -p stash @ {0}> Stash0.patch

  2. Застосуйте зміни вручну:

    git застосувати Stash0.patch

Якщо другий крок не вдасться, вам доведеться відредагувати файл Stash0.patch, щоб виправити помилки, а потім спробувати застосувати git знову.


Це практично і працездатно для випадку, коли я зробив рефакторинг на dir (видалив його та створив симпосилання з його назвою). Git не міг сказати, які зміни в моїй робочій копії були.
yclian

1
Це спрацювало чудово. Я не зміг застосувати приховування, хоча я впевнений, що моє робоче дерево чисте.
Шики

Так, мені довелося видалити рядки про двійковий файл.
Доріан

8

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

$ git stash save "опис поточних змін"
$ git stash pop скринька @ {1}

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


5
Але цей хлопець хоче, щоб два стаси застосовано!
Елазар Лейбович

@Elazar Ви читаєте питання. ОП просто хоче застосувати попередню сховку. Якщо ви впевнені, що слід змінити поточні зміни, рішення можна повторити: виконувати, виконувати, повторювати.
Вільям Перселл

Я думаю, що він хоче, щоб вони обоє були непорушними. Але знову ж таки, він може зробити їх двічі і розбити їх на одне ціле.
Елазар Лейбович

Я отримую помилку "... вже існує, немає замовлення ... Не вдалося відновити незавершені файли зі сховища"
Олександр Дубінський

6

Рішення Матіаса, безумовно, найближче до git stash pop - force (і справді, хай Git devs, давайте вже цей варіант!)

Однак якщо ви хочете зробити те саме, використовуючи лише команди git, ви можете:

  1. git commit -a -m "Виправити"
  2. git stash pop
  3. git commit -a --імен
  4. git reset HEAD ~

Іншими словами, прийміть на себе зобов’язання (які ми ніколи не будемо наполягати) на своїх поточних змінах. Тепер, коли ваша робоча область чиста, виведіть свій приклад. Тепер виконайте приховані зміни як доповнення до попереднього зобов’язання. Зробивши, що тепер у вас є обидва набори змін, об'єднані в один комітет ("Виправлення"); просто скиньте (--soft НЕ - важко, так що насправді нічого не втрачено) ваш замовлення на "один до того, як здійснити", і тепер у вас є обидва набори змін, повністю не видалені.

** редагувати * *

Я просто зрозумів, що насправді навіть простіше; ви можете повністю пропустити крок 3, тому ...

  1. git commit -a -m "Виправити"
  2. git stash pop
  3. git reset HEAD ~

(Здійснити поточні зміни, спливати приховані зміни, скинути спочатку виконання зобов’язань, щоб об'єднати обидва набори змін у непосланому стані.)


4

Жодна з цих відповідей насправді не спрацьовує, якщо ви опинитесь у цій ситуації, як я сьогодні. Незалежно від того, скільки git reset --hardя зробив, мене ніде не було. Моя відповідь (офіційною жодним чином не була):

  1. З’ясуйте хеш-використання git reflog --all
  2. Об’єднайте хеш із галуззю, яка вас цікавить

1
Велике спасибі Яр. Мене розчарувало те, як зараз Гіт дивно поводився на моєму місцевому репо, та сама проблема, яку ти описав.
yclian

4

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

[alias]
        apply-stash-to-dirty-working-tree = !git stash show -p | git apply && git stash drop

Тепер я можу просто набрати

git apply-stash-to-dirty-working-tree

що чудово працює для мене.

(Ваш пробіг може залежати від цього довгого псевдоніму. Але мені подобається доза багатослівності, коли мова йде про завершення баш.)


3

Ви можете застосувати сховище до "брудного" дерева, зробивши git addпоетапно будь-які внесені вами зміни, таким чином очистивши дерево. Тоді ви можете git stash popзастосувати приховані зміни, без проблем.


2

У вас є файли, які були змінені, але не зафіксовані. Або:

git reset --hard HEAD (to bring everything back to HEAD)

або, якщо ви хочете зберегти свої зміни:

git checkout -b new_branch
git add ...
git commit
git checkout -b old_branch
git stash pop

1
@MikeCooper - я думаю, що він просто мав на увазі додати все, що ви хочете додати, перш ніж зробити це.
sscirrus

0

У мене була така ж проблема, але в git були файли, що не змінювались. Виявляється, у мене був файл index.lock, який лежав навколо. Видалення його вирішило проблему.


0

Я не зміг змусити більшість із них працювати; чомусь завжди вважає, що я маю локальні зміни у файлі. Я не можу застосувати приховану скриньку, патчі не застосовуватимуться checkoutта reset --hardне вдаються. Що, нарешті, працювало - це збереження сховища як філії git stash branch tempbranchname, а потім звичайне злиття гілки: git checkout masterі git merge tempbranchname. Від http://git-scm.com/book/en/Git-Tools-Stashing :

Якщо ви хочете знову простіше перевірити приховані зміни, ви можете запустити гілку прихованої гілки, яка створює для вас нову гілку, перевіряє зобов’язання, на яких ви були, коли ви призупинили свою роботу, знову додає свою роботу там, а потім скидає приховувати, якщо він успішно застосовується

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.