Dlaczego nie można zastosować skrytki do katalogu roboczego?


96

Nie mogę zastosować skrytki z powrotem do katalogu roboczego.

Mała historia:

Najpierw próbowałem wprowadzić pewne wprowadzone zmiany, ale powiedział: „nie, nie możesz, najpierw pociągnij”… OK, w takim razie wyciągnę rzeczy z GitHub, a następnie wprowadzę zmiany. Kiedy próbowałem wyciągnąć, powiedział, że mam zmiany, które zostaną nadpisane i że powinienem je ukryć. OK, ukryłem zmiany ... wyciągnąłem i popchnąłem wprowadzone zmiany. Ale teraz nie mogę przywrócić niezatwierdzonych zmian, nad którymi pracowałem.

To jest błąd:

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

Na pewno nie rozumiem jeszcze wszystkich pojęć gita, trochę mnie mylą ... może zrobiłem coś złego.

Byłoby wspaniale, gdyby ktoś mógł mi pomóc rozwiązać ten problem ... Przeszukuję google i wszystko od ponad godziny i jeszcze nie znalazłem rozwiązania.

Pomoc jest bardzo ceniona. Dzięki!

Odpowiedzi:


74

Wygląda na to, że twoja skrytka zawiera nieśledzony plik, który został następnie dodany do repozytorium. Kiedy spróbujesz go sprawdzić, git słusznie odmawia, ponieważ nadpisałby istniejący plik.

Aby to naprawić, możesz zrobić coś takiego, jak usunięcie tego pliku (jest w porządku, nadal jest w repozytorium), zastosowanie skrytki, a następnie zastąpienie przechowywanej wersji pliku wersją w repozytorium.

Edycja: Jest również możliwe, że plik został utworzony tylko w drzewie roboczym bez dodania go do repozytorium. W takim przypadku nie usuwaj pliku lokalnego, a raczej:

  1. przenieś go gdzie indziej
  2. zastosuj skrytkę
  3. ręcznie scal dwie wersje plików (drzewo robocze vs. przeniesione).

2
Czy jest jakiś sposób, żebym mógł uniknąć konieczności przechowywania rzeczy w przyszłości ... Pochodzę z SVN i wygląda to tak naprzód ... po prostu aktualizujesz, rozwiązujesz konflikty i zatwierdzasz. Git nie może być tak trudny, że muszę dodać 2 kroki w cyklu. Dzięki jeszcze raz!
Miguel Angelo

2
@Miguel: Przechowywanie nie jest przeszkodą. Jest to dodatkowe narzędzie dostarczane przez Git, które pozwala usprawnić przepływ pracy i uniknąć konfliktów i nieczystych zatwierdzeń. git-scm.com/docs/git-stash
Koraktor

8
Chociaż odpowiedź jest prawidłowa, naprawdę nie jestem pewien, czy git jest w tym „poprawny”. Pliki znajdują się w repozytorium, więc nie ma niebezpieczeństwa utraty danych. dlaczego po prostu nie zastosować zmian? Zobacz ten wątek - git.661346.n2.nabble.com/stash-refuses-to-pop-td7453780.html
studgeek

5
Myślę, że ta odpowiedź nie jest najbardziej pomocna. git stashpowinno pomóc w szybkim tworzeniu kopii zapasowych lokalnych zmian. Ręczne usuwanie zestawu plików w celu jego przywrócenia przerywa przepływ. git stash branchPodejście w drugiej odpowiedź brzmi lepiej, ale nadal znacznie więcej niż podręcznik pożądane.
bentolor

Ta odpowiedź była dla mnie najlepsza w takiej samej sytuacji. Po tym, jak wyjąłem skrytkę, przeszedłem przez scalanie, tak jak oczekiwałem od początku.
Billy Lazzaro

58

Najbezpieczniejszym i najłatwiejszym sposobem byłoby prawdopodobnie ponowne przechowywanie rzeczy:

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

Następnie, jeśli jesteś zadowolony z wyniku, możesz zadzwonić

git stash drop

aby usunąć „bezpieczny” schowek.


2
Dziękuję Ci za to, uratował mnie od bólu i cierpienia!
danjarvis

9
Stash pop zastosuje i upuści oryginalną skrytkę. Po prostu, aby być bezpiecznym, applyzamiast pop.
Hilbrand Bouwkamp

2
W rzeczywistości popjest połączeniem applyi drop, ale będzie tylko dropwtedy, gdy applyzadziała bez konfliktów. Ale tak, applyjest zwykle bezpieczniejsze.
Koraktor

2
Zakłada się, że nie ma innych zmian w katalogu roboczym, które chcesz zachować. W przypadku tego konkretnego pytania sugeruje (ale nie mówi wprost), że jest w stanie czystym, ale chciałem zwrócić na to uwagę innym, którzy przyjeżdżają tutaj z lokalnymi zmianami.
studgeek

1
To rozwiązuje problem tylko wtedy, gdy konfliktowe problemy nie zostały popełnione . Otrzymujesz dokładnie tę samą wiadomość, gdy zostaną popełnione (np. Z czystym kasą), a wtedy nic to nie zmieni ...
Jasper,

56

Jak wspomniał @bentolo, możesz ręcznie usunąć pliki, na które narzeka, zmienić gałęzie, a następnie ręcznie dodać je z powrotem. Ale ja osobiście wolę pozostać „w gicie”.

Najlepszym sposobem na to jest przekształcenie skrytki w gałąź. Gdy jest to gałąź, możesz normalnie pracować w git, używając normalnych technik / narzędzi związanych z gałęziami, które znasz i lubisz. W rzeczywistości jest to użyteczna ogólna technika pracy ze skrytkami, nawet jeśli nie masz wymienionego błędu. Działa dobrze, ponieważ skrytka naprawdę jest zatwierdzeniem pod okładkami (patrz PS).

Przekształcenie skrytki w gałąź

Poniższe polecenie tworzy gałąź na podstawie HEAD, gdy skrytka została utworzona, a następnie stosuje ją (nie zatwierdza jej).

git stash branch STASHBRANCH

Praca z „stash branch”

To, co zrobisz dalej, zależy od relacji między skrytką a miejscem, w którym znajduje się twoja docelowa gałąź (którą nazwałem ORIGINALBRANCH).

Opcja 1 - Odbuduj gałąź skrytki normalnie (dużo zmian od czasu skrytki)

Jeśli dokonałeś wielu zmian w swoim ORIGINALBRANCH, prawdopodobnie najlepiej będzie traktować STASHBRANCH jak każdy lokalny oddział. Zatwierdź zmiany w STASHBRANCH, zmień bazę na ORIGINALBRANCH, a następnie przełącz się na ORIGINALBRANCH i ponownie bazuj / scal zmiany STASHBRANCH na nim. Jeśli występują konflikty, postępuj z nimi normalnie (jedną z zalet tego podejścia jest to, że możesz zobaczyć i rozwiązać konflikty).

Opcja 2 - Zresetuj oryginalną gałąź, aby pasowała do skrytki (ograniczone zmiany od czasu skrytki)

Jeśli po prostu schowałeś, zachowując kilka etapowych zmian, a następnie zatwierdziłeś, a wszystko, co chcesz zrobić, to uzyskać dodatkowe zmiany, które nie zostały wprowadzone w fazie przechowywania, możesz wykonać następujące czynności. Powróci do oryginalnej gałęzi i indeksu bez zmiany kopii roboczej. Efektem końcowym będą dodatkowe zmiany w skrytce w kopii roboczej.

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

tło

Skrytki to zatwierdzenia, polubienia gałęzi / tagów (nie łatki)

PS, Kuszące jest myślenie o skrytce jako o łatce (tak jak o zatwierdzeniu jako o łatce), ale skrytka jest w rzeczywistości zatwierdzeniem przeciwko HEAD, kiedy została stworzona. Kiedy aplikujesz / wyskakujesz, robisz coś podobnego do wybierania wiśniowego w swojej bieżącej gałęzi. Pamiętaj, że gałęzie i tagi są tak naprawdę tylko odniesieniami do zatwierdzeń, więc pod wieloma względami skrytki, gałęzie i tagi są po prostu różnymi sposobami wskazywania na zatwierdzenie (i jego historię).

Czasami potrzebne, nawet jeśli nie wprowadziłeś zmian w katalogu roboczym

PPS, możesz potrzebować tej techniki po prostu używając skrytki z opcją --patch i / lub --include-untracked. Nawet bez zmiany katalogów roboczych te opcje mogą czasami tworzyć skrytkę, której nie można po prostu ponownie zastosować. Muszę przyznać, że nie do końca rozumiem, dlaczego. Zobacz http://git.661346.n2.nabble.com/stash-refuses-to-pop-td7453780.html, aby zapoznać się z dyskusją.


5
Tę odpowiedź należy oznaczyć jako rozwiązanie, ponieważ dostarcza najbardziej pomocnych wskazówek, jak najskuteczniej rozwiązać „zablokowaną skrytkę”. Może ulepszyć to, wspominając najpierw o „prostym rozwiązaniu usuwania”, a jako drugiej opcji o rozwiązaniu gałęzi.
bentolor

8
Wydaje się, że „git stash branch STASHBRANCH” nie działa, jeśli masz do czynienia z takim scenariuszem (pojawia się dokładnie ten sam komunikat o błędzie, co w przypadku pop). Być może będziesz musiał wcześniej zresetować git.

+1 Wpadłem w bałagan spaghetti z zatwierdzeniami, zmianami, przechowywaniem itp., Itp. To mnie z tego wyciągnęło,
wrzucając skrytkę

Dziękuję za wyjaśnienie, dlaczego skrytki nie są łatami i jak są przywiązane do HEAD (w momencie skrytowania). To ma sens. - Więc ... przypuszczam, że są przypadki, w których tworzenie łatki jest bardziej elastyczne / przenośne / wygodniejsze niż skrytka (jak wspomniałeś: przy wielu zmianach), dzięki czemu można ją zastosować w dowolnym miejscu (i jest tylko kwestia rozwiązywania konfliktów). Może git stash show -ppomaga w tworzeniu skrytki -> * patch *.
Kamafeather

39

Rozwiązanie: musisz usunąć plik, o którym mowa, a następnie ponownie spróbować ukryć pop / zastosować i powinien przejść. Nie usuwaj innych plików, tylko te wymienione w błędzie.

Problem: czasami Git jest do niczego. Po uruchomieniu git stash -uzawiera nieśledzone pliki (fajnie!), Ale nie usuwa tych nieśledzonych plików i nie wie, jak zastosować ukryte niezarejestrowane pliki na resztkach (nie fajne!), Co naprawdę sprawia, że -uopcja jest całkiem bezużyteczna.


3
Przyjąłbym tę odpowiedź, gdyby to było moje pytanie. Dzięki @qwertzguy, twoja odpowiedź rozwiązała mój problem,
Kobus Myburgh

Sam napotkałem ten sam problem, git stash pop nie działałby, dopóki nie usunąłem tych plików - wtedy napotkałem konflikt z plikiem, który spowodował odrzucenie skrytki. Ale zamiast usunięcia niezarejestrowanych plików, które pozostawiły je za sobą. Uwaga dla przyszłego siebie, trzymaj się z daleka odgit stash -u
notzippy.

Zła rada, jeśli potrzebujesz części z obu wersji plików, których dotyczy problem.
Walf,

2
„nie usuwa nieśledzonych plików” … i nie wyświetla ich w git stash show. Ta odpowiedź sprawiła, że ​​żarówka się włączyła.
jscs

2
plus jeden dla Gita czasami jest do bani.
Harish

29

Aby zamiast tego zastosować różnice w kodzie w skrytce jako łatkę, użyj następującego polecenia:

git stash show --patch | patch -p1

11
Zwykle lepiej jest wyjaśnić rozwiązanie, zamiast po prostu publikować kilka wierszy anonimowego kodu. Możesz przeczytać Jak napisać dobrą odpowiedź , a także wyjaśnić odpowiedzi w całości oparte na kodzie .
Massimiliano Kraus

To działa dla mnie, ponieważ łatka z git stash show --patchnie zawiera niezatwierdzonych plików.
Steven Shaw

Ta odpowiedź bardzo mi pomogła, ponieważ nie mogłem wyrzucić mojej skrytki z powodu wielu zmian w moim repozytorium od czasu jej wypchnięcia.
Erik Finnman,

1

Zdarzyło mi się to wiele razy, przechowuję nieśledzone pliki, git stash -uktóre w końcu są dodawane do repozytorium i nie mogę już zastosować ukrytych zmian.

Nie mogłem znaleźć sposobu, aby wymusić git stash pop/applywymianę plików, więc najpierw usuwam lokalne kopie niezarejestrowanych plików, które zostały ukryte ( bądź ostrożny, ponieważ usunie to wszelkie niezatwierdzone zmiany ), a następnie zastosuję ukryte zmiany :

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

Wreszcie, używam git status, git difforaz inne narzędzia do sprawdzania i włożyć z powrotem fragmentów usuniętych plików, jeśli czegoś brakuje.


Jeśli masz niezatwierdzone zmiany, które chcesz zachować, możesz najpierw utworzyć tymczasowe zatwierdzenie:

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

Użyj dowolnych narzędzi, aby scalić wcześniej zatwierdzone zmiany z powrotem do plików lokalnych i usunąć fikcyjne zatwierdzenie:

git reset HEAD~1

0

Moja podobnie zablokowana operacja pop była spowodowana ignorowaniem pozostałych plików (zobacz plik .gitignore). Status Git pokazał mi śledzenie i nieśledzenie, ale moje działania nie wyczyściły ignorowanych plików.

Szczegóły: użyłem git stash save -a, sprawdziłem wzorzec, aby skompilować i zobaczyć oryginalne zachowanie, a następnie próbowałem odłożyć wszystko z powrotem, aby kontynuować edycję. Kiedy sprawdzałem swoją gałąź i próbowałem wyskoczyć, moje zignorowane pliki były tam jeszcze przed zapisaniem skrytki. Dzieje się tak, ponieważ wyewidencjonowanie wzorca dotyczyło tylko zatwierdzonych plików - nie wyczyściło zignorowanych plików. Więc pop nie powiódł się, mówiąc zasadniczo, że nie chciał przywracać moich przechowywanych zignorowanych plików na plikach, które nadal tam były. Szkoda, że ​​nie mogłem znaleźć sposobu, aby rozpocząć z nimi sesję scalania.

Ostatecznie zwykłem git clean -f -d -xusuwać ignorowane pliki. Co ciekawe, z moich ~ 30, 4 pliki pozostały po czyszczeniu (zakopane w podkatalogach). Będę musiał dowiedzieć się, w jakiej kategorii się znajdują, że trzeba było je ręcznie usunąć.

Wtedy mój tato odniósł sukces.



-1

Inne rozwiązanie:

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

Błąd wspomniany w pytaniu jest spowodowany przez plik, który istnieje zarówno w stosie, jak i w katalogu roboczym. Czyszczenie rozwiązuje problem tylko wtedy, gdy ten plik nie jest śledzony, co z pewnością nie zawsze ma miejsce (a nie w przypadku OP, ponieważ otrzymał plik z wyciągnięcia).
Xavier Poinas

-1

Z Git 2.14.x / 2.15 (Q3 2017), qwertzguy „s rozwiązanie od 2014 roku nie będzie już konieczne.

Przed trzecim kwartałem 2017 r. Trzeba było usunąć dany plik, a następnie ponownie spróbować ukryć plik pop / zastosować.
Z następną wersją Gita nie będziesz musiał tego robić.

Zobacz commit bbffd87 (11 sierpnia 2017) autorstwa Nicolasa Morey-Chaisemartin ( nmorey) .
(Scalone przez Junio ​​C Hamano - gitster- w zatwierdzeniu 0ca2f32 , 23 sierpnia 2017 r.)

stash: wyczyść nieśledzone pliki przed resetowaniem

W przypadku wywołania git stash -urepozytorium zawierającego plik, który nie jest już ignorowany z powodu bieżącej modyfikacji gitignorepliku, plik ten jest przechowywany, ale nie usuwany z drzewa roboczego.
Dzieje się tak, ponieważ git-stashnajpierw wykonuje się polecenie a, reset --hardktóre usuwa .gitignoremodyfikację pliku, a następnie wywołuje git clean, pozostawiając plik nietknięty.
Powoduje git stash popto niepowodzenie z powodu istniejącego pliku .

Ta poprawka po prostu przełącza kolejność między czyszczeniem a resetowaniem i dodaje test dla tego przypadku.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.