Git stash: «Не удается применить к грязному рабочему дереву, пожалуйста, внесите изменения» - PullRequest
129 голосов
/ 01 сентября 2009

Я пытаюсь применить изменения, которые я спрятал ранее с git stash pop, и получаю сообщение:

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

Есть предложения о том, как с этим бороться?

Ответы [ 11 ]

192 голосов
/ 17 сентября 2010

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

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

В основном это

  1. создает патч
  2. передает эту команду
  3. если есть какие-либо конфликты, их необходимо разрешить с помощью трехстороннего слияния
  4. Если применить (или объединить) успешно, он удаляет только что примененный тайник ...

Интересно, почему для git stash pop не существует опции -f (force), которая должна точно вести себя так, как указано выше в одной строке.

Тем временем вы можете добавить этот однострочный псевдоним git:

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

Спасибо @SamHasler за указание на параметр -3, который позволяет разрешать конфликты напрямую с помощью трехстороннего слияния.

55 голосов
/ 24 июля 2012

Я делаю это так:

git add -A
git stash apply

и затем (необязательно):

git reset
9 голосов
/ 31 марта 2010

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

Например, скажем, вы хотите применить stash @ {0} к грязному дереву:

  1. Экспорт stash @ {0} в виде патча:

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

  2. Вручную применить изменения:

    git apply Stash0.patch

Если второй шаг не удался, вам придется отредактировать файл Stash0.patch, чтобы исправить все ошибки, а затем снова попробовать git apply.

8 голосов
/ 01 сентября 2009

Либо очистите ваш рабочий каталог с помощью git reset, зафиксируйте изменения, либо, если вы хотите сохранить текущие изменения, попробуйте:

$ git stash save "description of current changes"
$ git stash pop stash@{1}

Это сохранит текущие изменения, а затем выдвинет второетайник из стопки.

6 голосов
/ 17 апреля 2012

Решение Матиаса определенно ближе всего к git stash pop --force (и действительно, давайте, разработчики Git, давайте уже получим эту опцию!)

Однако, если вы хотите сделать то же самое, используя только команды git, вы можете:

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. git commit -a --amend
  4. git reset HEAD ~

Другими словами, сделайте коммит (который мы никогда не будем продвигать) ваших текущих изменений. Теперь, когда ваше рабочее пространство чистое, вставьте свой тайник. Теперь внесите изменения в тайник в качестве дополнения к вашему предыдущему коммиту. Сделав это, вы теперь объединяете оба набора изменений в один коммит («Fixme»); просто сбросьте (--soft NOT --hard, так что на самом деле ничего не потеряно) вашу проверку на «один до этого коммита», и теперь у вас есть оба набора изменений, полностью незафиксированные.

** EDIT **

Я только что понял, что на самом деле это даже проще; Вы можете полностью пропустить шаг 3, так что ...

  1. git commit -a -m "Fixme"
  2. git stash pop
  3. git reset HEAD ~

(Зафиксируйте текущие изменения, вытолкните спрятанные изменения, сбросьте первый коммит, чтобы объединить оба набора изменений в незафиксированное состояние.)

4 голосов
/ 26 апреля 2011

Я также нашел, что решение Матиаса Леппича прекрасно работает, поэтому я добавил псевдоним для него в свой глобальный .gitconfig

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

Теперь я могу просто набрать

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

, который прекрасно работает для меня.

(Ваш пробег может отличаться от этого длинного псевдонима. Но мне нравится доза многословия, когда он идет с завершением bash.)

4 голосов
/ 28 октября 2010

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

  1. Выясните, как использовать хэш для тайника git reflog --all
  2. Слияние этого хэша с веткой, в которой вы заинтересованы
3 голосов
/ 20 января 2012

Вы можете применить тайник к «грязному» дереву, выполнив git add, чтобы внести любые изменения, которые вы сделали, таким образом очистив дерево. Тогда вы можете git stash pop и применить спрятанные изменения, без проблем.

2 голосов
/ 01 сентября 2009

У вас есть файлы, которые были изменены, но не зафиксированы. Или:

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
0 голосов
/ 23 марта 2013

Мне не удалось заставить большинство из них работать; по какой-то причине он всегда думает, что у меня есть локальные изменения в файле. Я не могу применить тайник, патчи не будут применены, checkout и reset --hard потерпят неудачу. В конечном итоге сработало сохранение тайника как ветви с git stash branch tempbranchname, а затем обычное слияние ветвей: git checkout master и git merge tempbranchname. От http://git -scm.com / book / ru / Git-Tools-Stashing :

Если вам нужен более простой способ снова проверить сохраненные изменения, вы можете запустите ветку git stash, которая создаст для вас новую ветку коммит, на котором вы были, когда вы спрятали свою работу, повторно применяет вашу работу там, а затем сбрасывает тайник, если он успешно применяется

...