Skrytka Git: „Nie można zastosować do brudnego drzewa roboczego, wprowadź zmiany”

133

Próbuję zastosować zmiany, które zapisałem wcześniej git stash popi otrzymuję komunikat:

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

Jakieś sugestie, jak sobie z tym poradzić?

średnia
źródło

Odpowiedzi:

196

Kiedy muszę zastosować ukryte zmiany w brudnej kopii roboczej, np. Wyjąć więcej niż jeden zestaw zmian ze schowka, używam:

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

W zasadzie to

  1. tworzy łatkę
  2. przesyła to do polecenia zastosuj
  3. jeśli wystąpią jakiekolwiek konflikty, należy je rozwiązać za pomocą scalania trójstronnego
  4. jeśli zastosowanie (lub scalenie) powiodło się, upuszcza właśnie zastosowany przedmiot ze skrytki ...

Zastanawiam się, dlaczego nie ma opcji -f(wymuszenia), dla git stash popktórej powinno się dokładnie zachowywać jak powyższy jednolinijkowy.

W międzyczasie możesz dodać ten jednolinijkowy alias jako alias git:

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

Podziękowania dla @SamHasler za wskazanie -3parametru, który pozwala rozwiązywać konflikty bezpośrednio przez 3-way merge.

muhqu
źródło
Jest git stash show -p | git applyinny niż git stash apply?
Factor Mystic
1
Jo Factor, git stash applynie zastosuje zachowanych zmian, jeśli masz brudną kopię roboczą. Możesz więc zobaczyć, git stash show -p | git applyże obowiązuje jakiś wymuszony skryt.
muhqu
1
nie pomaga Ale pomoc: git zresetuj HEAD i usuń zmiany po tym.
Roger Alien
4
Dla jednego z plików wyświetlany jest komunikat „błąd: poprawka nie powiodła się ... poprawka nie ma zastosowania”. Chciałbym, żeby dał konflikt scalania.
Aleksandr Dubinsky
1
To rozwiązanie nie działało dla mnie, zawodziło z error: <file> does not match indexkażdym zmodyfikowanym plikiem. Jednak inne rozwiązanie zadziałało.
silvenon
57

Robię to w ten sposób:

git add -A
git stash apply

a następnie (opcjonalnie):

git reset
Sergii Mostovyi
źródło
2
+1! Jest to prostsze niż inne rozwiązania, które obejmują generowanie poprawek lub zmiany zatwierdzeń, i zapewnia bezpieczne odizolowanie lokalnych zmian od zastosowanych zmian w skrytce, dopóki nie masz pewności, że zostały one prawidłowo scalone.
peterflynn,
Pojawia się błąd „… już istnieje, brak wypisania… Nie można przywrócić niezatwierdzonych plików z magazynu”
Aleksandr Dubinsky
2
Użyłem git add -u, co jest jak -Az wyjątkiem tego, że nie dodaje nieśledzonych plików.
Brad Cupit
9

Możesz to zrobić bez konieczności przechowywania bieżących zmian, eksportując żądaną skrytkę jako plik poprawki i ręcznie ją stosując.

Załóżmy na przykład, że chcesz zastosować stash @ {0} do brudnego drzewa:

  1. Eksportuj magazyn @ {0} jako poprawkę:

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

  2. Ręcznie zastosuj zmiany:

    git zastosuj Stash0.patch

Jeśli drugi krok się nie powiedzie, będziesz musiał wyedytować plik Stash0.patch, aby naprawić wszelkie błędy, a następnie ponownie spróbować zastosować git.

Ishan
źródło
Jest to praktyczne i wykonalne w przypadku, gdy dokonałem refaktoryzacji w katalogu (usunąłem go i utworzyłem dowiązanie symboliczne z jego nazwą). Git nie mógł powiedzieć, jakie były zmiany w mojej kopii roboczej.
yclian
1
To działało świetnie. Nie udało mi się założyć skrytki, chociaż jestem prawie pewien, że moje drzewo robocze jest czyste.
Shiki,
Tak, musiałem usunąć linie dotyczące pliku binarnego.
Dorian
8

Albo wyczyść katalog roboczy za pomocą git reset, zatwierdź zmiany lub, jeśli chcesz zachować bieżące zmiany, spróbuj:

$ git stash save "opis bieżących zmian"
$ git stash pop stash @ {1}

Spowoduje to ukrycie bieżących zmian, a następnie zdejmie drugą skrytkę ze stosu.

Williama Pursella
źródło
5
Ale ten gość chce zastosować te dwie skrytki!
Elazar Leibovich
@Elazar Czytasz pytanie. PO chce tylko zastosować poprzednią skrytkę. Jeśli masz rację, że bieżące zmiany mają zostać zachowane, rozwiązanie można powtórzyć: pop, zatwierdzenie, powtórz.
William Pursell,
Myślę, że chce, żeby oboje byli niezaangażowani. Ale z drugiej strony może zatwierdzić je dwukrotnie i zgnieść je w jednym zatwierdzeniu.
Elazar Leibovich,
Pojawia się błąd „… już istnieje, brak wypisania… Nie można przywrócić niezatwierdzonych plików ze schowka”
Aleksandr Dubinsky
6

Rozwiązanie Mathiasa jest zdecydowanie najbliższe git stash pop --force (i naprawdę, chodźmy do twórców Git, pobierzmy już tę opcję!)

Jeśli jednak chcesz zrobić to samo, używając tylko poleceń git, możesz:

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

Innymi słowy, dokonaj zatwierdzenia (którego nigdy nie będziemy pchać) aktualnych zmian. Teraz, gdy twoje miejsce pracy jest czyste, wyrzuć swój schowek. Teraz zatwierdź zmiany w skrytce jako poprawkę do twojego poprzedniego zatwierdzenia. Uczyniwszy to, masz teraz oba zestawy zmian połączone w jednym zatwierdzeniu („Fixme”); po prostu zresetuj (- miękkie NIE - twarde, więc nic nie jest stracone) twój checkout do "jednego przed tym zatwierdzeniem" i teraz masz oba zestawy zmian, całkowicie niezatwierdzone.

** EDYTUJ * *

Właśnie zdałem sobie sprawę, że to jeszcze łatwiejsze; możesz całkowicie pominąć krok 3, więc ...

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

(Zatwierdź bieżące zmiany, usuń ukryte zmiany, zresetuj pierwsze zatwierdzenie, aby uzyskać połączenie obu zestawów zmian w stanie niezatwierdzonym).

machineghost
źródło
4

Żadna z tych odpowiedzi nie działa, jeśli znajdziesz się w takiej sytuacji, jak ja dzisiaj. Bez względu na to, ile git reset --hardzrobiłem, nic mnie to nie dało. Moja odpowiedź (w żadnym wypadku nie była oficjalna):

  1. Dowiedz się, jakie jest użycie skrótu w skrytce git reflog --all
  2. Połącz ten skrót z interesującą Cię gałęzią
Dan Rosenstark
źródło
1
Wielkie dzięki Yar. Byłem sfrustrowany tym, jak Git dziwnie zachowywał się teraz w moim lokalnym repozytorium, ten sam problem, który opisałeś.
yclian
4

Uważam również, że rozwiązanie Mathiasa Leppicha działa świetnie, więc dodałem dla niego alias do mojego globalnego .gitconfig

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

Teraz mogę po prostu pisać

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

co działa świetnie dla mnie.

(Twój przebieg może się różnić w przypadku tej długiej nazwy aliasu. Ale lubię dawkę szczegółowości, jeśli chodzi o zakończenie bash).

mat
źródło
3

Możesz przyłożyć skrytkę do „brudnego” drzewa, wykonując a, git addaby przygotować zmiany, które wprowadziłeś, a tym samym oczyścić drzewo. Wtedy możesz git stash popi zastosować zapisane zmiany, bez problemu.

Chris Vandevelde
źródło
2

Masz pliki, które zostały zmodyfikowane, ale niezatwierdzone. Zarówno:

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

lub, jeśli chcesz zapisać zmiany:

git checkout -b new_branch
git add ...
git commit
git checkout -b old_branch
git stash pop
brool
źródło
1
@MikeCooper - myślę, że miał na myśli po prostu dodanie wszystkiego, co chcesz dodać przed zatwierdzeniem.
sscirrus
0

Miałem ten sam problem, ale git nie miał żadnych zmienionych plików. Okazało się, że miałem plik index.lock, który leżał w pobliżu. Usunięcie go rozwiązało problem.

zapakowane
źródło
0

Większość z nich nie działała; z jakiegoś powodu zawsze myśli, że mam lokalne zmiany w pliku. Nie mogę założyć skrytki, łaty się nie zastosują checkouti reset --hardzawodzą. Ostatecznie zadziałało zapisanie zapasu jako gałęzi za pomocą git stash branch tempbranchname, a następnie wykonanie normalnego scalania gałęzi: git checkout masteri git merge tempbranchname. Z http://git-scm.com/book/en/Git-Tools-Stashing :

Jeśli chcesz łatwiejszego sposobu ponownego przetestowania ukrytych zmian, możesz uruchomić git stash branch, który tworzy dla ciebie nową gałąź, sprawdza zatwierdzenie, na którym byłeś, kiedy przechowywałeś swoją pracę, ponownie stosuje tam twoją pracę, a następnie upuszcza stash, jeśli się powiedzie

rwilson04
źródło