Jak odzyskać ukryte niezaangażowane zmiany


693

Miałem kilka nieproszonych zmian w mojej gałęzi programistycznej i wykorzystałem je git stash, ale były pewne zmiany, które były bardzo ważne wśród tych, które zostały ukryte. Czy jest jakiś sposób na odzyskanie tych zmian?

Od tego czasu wprowadziłem pewne zmiany w plikach kodu ukrytego.

Czy jest jakaś szansa na odzyskanie ukrytych zmian w nowej gałęzi, jeśli to możliwe?


7
próbowałeś użyć „stash pop”?
Robert

Nie. Właściwie to jestem nowy. Ponieważ nie jestem w pełni świadomy wszystkich poleceń, nie próbowałem niczego innego! Nie chcę stracić tych zmian.
Aswathy P Krishnan,

33
Jeśli nie chcesz stracić ukrytych zmian, spróbuj użyć „git stash Apply”. Spowoduje to zastosowanie ukrytych zmian do bieżącej gałęzi, przy jednoczesnym zachowaniu skrytki. Jeśli wszystko jest w porządku, po nałożeniu skrytki możesz upuścić skrytkę, używając „git stash drop”
Robert

2
@robert Dziękuję za prostą odpowiedź w porównaniu do strasznie skomplikowanej (dla początkującego) zaakceptowanej odpowiedzi.
Saheel Godhane

Odpowiedzi:


1186

Łatwa odpowiedź na proste pytanie brzmi git stash apply

Po prostu sprawdź gałąź, w której chcesz wprowadzić zmiany, a następnie git stash apply. Następnie użyj, git diffaby zobaczyć wynik.

Po skończysz ze zmiany-z applydobrym wyglądem i masz pewność, że nie trzeba zapas każdy więcej- następnie użyć git stash drop, aby pozbyć się go.

Zawsze sugeruję używanie git stash applyzamiast git stash pop. Różnica polega na tym, że applypozostawia skrytkę w celu łatwego ponownego spróbowania apply, lub w celu patrzenia itp. Jeśli popjest w stanie wyodrębnić skrytkę, natychmiast dropją również zrobi , a jeśli nagle uświadomisz sobie, że chcesz ją gdzieś wyodrębnić w innym (w innej gałęzi), z --index, lub z innymi, to nie jest takie proste. Jeśli tak apply, możesz wybrać, kiedy drop.

To wszystko jest dość niewielkie w ten czy inny sposób, a dla nowicjusza, powinno być mniej więcej tak samo. (I możesz pominąć resztę tego!)


Co jeśli robisz bardziej zaawansowane lub bardziej skomplikowane rzeczy?

Istnieją co najmniej trzy lub cztery różne „sposoby używania skrytki git”. Powyższe dotyczy „sposobu 1”, „łatwego sposobu”:

  1. Zacząłeś od czystej gałęzi, pracowałeś nad pewnymi zmianami, a potem zdałeś sobie sprawę, że robisz je w niewłaściwej gałęzi. Chcesz tylko wprowadzić zmiany, które już masz, i przenieść je do innej gałęzi.

    Jest to łatwy przypadek opisany powyżej. Uruchom git stash save(lub zwykły git stash, to samo). Sprawdź drugi oddział i skorzystaj z niego git stash apply. To powoduje, że git łączy się z twoimi wcześniejszymi zmianami, używając raczej potężnego mechanizmu scalania git. Sprawdź wyniki dokładnie (za pomocą git diff), aby zobaczyć, czy ci się podobają, a jeśli tak, użyj git stash dropupuszczenia skrytki. Jesteś skończony!

  2. Zacząłeś pewne zmiany i ukryłeś je. Następnie przeniosłeś się do innej gałęzi i zacząłeś więcej zmian, zapominając, że masz te ukryte.

    Teraz chcesz zachować, a nawet przenieść te zmiany, i zastosować również swoją skrytkę.

    Możesz w rzeczywistości git stash saveponownie, ponieważ git stashtworzy „stos” zmian. Jeśli to zrobisz, masz dwie skrytki, jedną właśnie nazwaną stash- ale możesz także pisać stash@{0}- i jedną pisownię stash@{1}. Użyj git stash list(w dowolnym momencie), aby zobaczyć je wszystkie. Najnowszy ma zawsze najniższy numer. Kiedy Ty git stash dropupuszczasz najnowszy, a ten, który był, stash@{1}przenosi się na szczyt stosu. Jeśli miał nawet więcej, ten, który był stash@{2}stanie stash@{1}, i tak dalej.

    Możesz, applya następnie droptakże konkretną skrytkę: git stash apply stash@{2}i tak dalej. Porzucenie określonej skrytki przenumeruje tylko te o wyższych numerach. Ponownie, ten bez numeru jest również stash@{0}.

    Jeśli zgromadzisz dużo skrytek, może stać się dość nieuporządkowany (czy był to schowek, którego chciałem, stash@{7}czy był stash@{4}? Czekaj, właśnie nacisnąłem inny, teraz są 8 i 5?). Osobiście wolę przenieść te zmiany do nowej gałęzi, ponieważ gałęzie mają nazwy i cleanup-attempt-in-Decemberoznaczają dla mnie znacznie więcej stash@{12}. ( git stashPolecenie przyjmuje opcjonalną wiadomość zapisu, a te mogą pomóc, ale jakoś wszystkie moje skrytki właśnie się skończyły WIP on branch).

  3. (Bardzo zaawansowane) Użyłeś git stash save -plub dokładnie git addi / lub git rm-eded określone bity twojego kodu przed uruchomieniem git stash save. Miałeś jedną wersję w ukrytym indeksie / obszarze pomostowym, a drugą (inną) wersję w działającym drzewie. Chcesz to wszystko zachować. Więc teraz używasz git stash apply --index, a to czasami kończy się niepowodzeniem z:

    Conflicts in index.  Try without --index.
    
  4. Używasz git stash save --keep-index, aby przetestować „co zostanie popełnione”. Ten jest poza zakresem tej odpowiedzi; zamiast tego zobacz inną odpowiedź StackOverflow .

W przypadku skomplikowanych przypadków zalecam najpierw rozpocząć pracę w „czystym” katalogu roboczym, wprowadzając wszelkie zmiany, które teraz wprowadzasz (jeśli chcesz, w nowym oddziale). W ten sposób „gdzieś”, w którym je stosujesz, nie ma w tym nic więcej, a będziesz po prostu próbował ukryć zmiany:

git status               # see if there's anything you need to commit
                         # uh oh, there is - let's put it on a new temp branch
git checkout -b temp     # create new temp branch to save stuff
git add ...              # add (and/or remove) stuff as needed
git commit               # save first set of changes

Teraz jesteś na „czystym” punkcie wyjścia. A może wygląda to tak:

git status               # see if there's anything you need to commit
                         # status says "nothing to commit"
git checkout -b temp     # optional: create new branch for "apply"
git stash apply          # apply stashed changes; see below about --index

Najważniejszą rzeczą do zapamiętania jest to, że „skrytka” to zatwierdzenie, to tylko „zabawne / dziwne” zatwierdzenie, które nie jest „na gałęzi”. Do applywygląda praca na co commit zmienione i próbuje powtórzyć go gdziekolwiek jesteś teraz. Skrytka nadal będzie tam ( applyutrzymuje ją w pobliżu), więc możesz na nią spojrzeć więcej lub zdecydować, że to niewłaściwe miejsce applyi spróbować ponownie inaczej lub cokolwiek innego.


Za każdym razem, gdy masz skrytkę, możesz użyć jej, git stash show -paby zobaczyć uproszczoną wersję tego, co jest w skrytce. (Ta uproszczona wersja patrzy tylko na zmiany „ostatecznego drzewa roboczego”, a nie na zapisane zmiany indeksu, które --indexprzywracają osobno.) Polecenie „ git stash applybez” --indexpo prostu próbuje teraz dokonać tych samych zmian w katalogu roboczym.

Jest to prawdą, nawet jeśli masz już jakieś zmiany. applyKomenda chętnie stosują zapas do zmodyfikowanego katalogu roboczym (lub przynajmniej, aby spróbować go zastosować). Możesz na przykład zrobić to:

git stash apply stash      # apply top of stash stack
git stash apply stash@{1}  # and mix in next stash stack entry too

Możesz tutaj wybrać polecenie „zastosuj”, wybierając poszczególne skrytki do zastosowania w określonej kolejności. Zauważ jednak, że za każdym razem, gdy wykonujesz „scalanie git” i jak ostrzega dokumentacja scalania:

Odradzanie uruchamiania git z nietrywialnymi niezatwierdzonymi zmianami jest odradzane: chociaż jest to możliwe, może pozostawić cię w stanie, który trudno jest wycofać się w przypadku konfliktu.

Jeśli zaczynasz od czystego katalogu i wykonujesz tylko kilka git applyoperacji, łatwo jest się wycofać: użyj, git reset --hardaby wrócić do czystego katalogu i zmienić swoje applyoperacje. (Dlatego właśnie polecam zacząć od czystego katalogu roboczego, w tych skomplikowanych przypadkach).


Co z najgorszym możliwym przypadkiem?

Załóżmy, że robisz wiele zaawansowanych rzeczy Git i zrobiłeś skrytkę i chcesz git stash apply --index, ale nie możesz już zastosować zapisanej skrytki --index, ponieważ gałąź odbiegała zbytnio od czasu jej zapisania.

Po to git stash branchjest.

Jeśli ty:

  1. sprawdzeniu dokładnego popełnić byłaś kiedy zrobiłeś oryginału stash, a następnie
  2. utworzyć nowy oddział i na koniec
  3. git stash apply --index

próba ponownego utworzenia zmiany na pewno będą działać. To właśnie robi. (A następnie upuszcza skrytkę, ponieważ została pomyślnie zastosowana).git stash branch newbranch


Kilka ostatnich słów na temat --index(co to do cholery jest?)

To, co --indexrobi, jest proste do wyjaśnienia, ale nieco skomplikowane wewnętrznie:

  • Kiedy wprowadzasz zmiany, musisz je git add(lub „wystawić”) przed wprowadzeniem commit.
  • Tak więc, kiedy biegł git stash, to może być edytowany zarówno pliki fooi zorg, ale tylko jeden z tych inscenizacji.
  • Więc kiedy pytasz, aby uzyskać z powrotem stash, to może być miło, gdyby to git adds addrzeczy Ed i robi nie git add nieokreślone dodane rzeczy. Oznacza to, że jeśli addedytowałeś, fooale nie zorgwróciłeś, zanim to zrobiłeś stash, może być miło mieć taką samą konfigurację. To, co zostało zainscenizowane, powinno zostać ponownie zainscenizowane; to, co zostało zmodyfikowane, ale nie ustawione, powinno być ponownie zmodyfikowane, ale nie ustawione.

--indexFlagę applypróbuje ustawić rzeczy ten sposób. Jeśli twoje drzewo robocze jest czyste, zwykle działa to po prostu. Jeśli jednak w twoim drzewie roboczym są już zainstalowane elementy add, możesz zobaczyć, jak mogą występować tutaj problemy. Jeśli pominąć --indexThe applyoperacja nie próbuje zachować cały wystawił / Unstaged konfigurację. Zamiast tego po prostu wywołuje maszynę scalającą git, używając zatwierdzenia drzewa roboczego w „stash bag” . Jeśli nie zależy ci na zachowaniu etapowym / niestacjonarnym, pominięcie --indexgo znacznie ułatwia git stash applyzrobienie tego.


2
Nie rozumiem twojego komentarza. Masz na myśli: uciekłeś git stash pop? Czy masz na myśli: edytowałeś niektóre pliki, ale nie uruchomiłeś git stashsię jeszcze? Czy masz na myśli coś zupełnie innego?
torek

1
Tak. Uwaga: w mojej (długiej) edycji polecam zatwierdzenie tego, co masz teraz, przed applyumieszczeniem skrytki. Nie musisz tego robić, ale sprawia, że ​​jest ci o wiele łatwiej. Możesz użyć rebase -ido zmiażdżenia wielu zatwierdzeń lub wybrania poszczególnych zmian, czy cokolwiek, później.
torek

1
Tak: git stash apply --index(pamiętaj o dwóch myślnikach). Jeśli pominiesz --index, nic wielkiego; Jedynym punktem --indexjest utrzymanie konfiguracji etapowej / niestacjonarnej. (Najprawdopodobniej nie miałeś żadnej specjalnej konfiguracji.) Następnie git statusitd. I dodaj / zatwierdź zgodnie z życzeniem itp. Kiedy (i tylko wtedy) skończysz ze skrytką, użyj, git stash dropaby ją odrzucić.
torek

1
Tak długo, jak przechowujesz (nie droplub pop) ukrytą skrzynkę, zawsze masz oryginalny ukryty kod bezpieczny w zatwierdzeniu, ponieważ ukryta jest zatwierdzona! Jeśli chcesz go odzyskać dokładnie, ale na gałęzi, użyj git stash branch(zobacz tę sekcję powyżej lub książkę Pro Git w odpowiedzi Shunyi ). Możesz wtedy git checkoutgit cherry-pick
przejść do

2
@ChuckWolber: Konwencje nazewnictwa Gita pozostawiają wiele do życzenia (ile różnych znaczeń możemy przypisać słowom „zdalne”, „śledzące” i „rozgałęzione” ?!). Warto jednak zauważyć, że można zastosować skrytkę do czegoś niezwiązanego z oryginalną skrytką.
torek

57
git stash pop

przywróci wszystko na miejsce

zgodnie z sugestiami w komentarzach, możesz użyć, git stash branch newbranchaby zastosować skrytkę do nowej gałęzi, która jest taka sama jak uruchomienie:

git checkout -b newbranch
git stash pop

Dzięki za pomoc. Czy mogę wprowadzić te zmiany do nowego oddziału? Obecnie jestem w
fazie

3
git stash branch newbranch, utworzy nowy oddział ze zmianami ukrytymi.
Robert

3
@robert: git stash branch newbranchrzeczywiście to zrobi; ale pamiętaj, że tworzy on nową gałąź z rodzicem ustawionym na zatwierdzenie, które było HEADw momencie, w którym stashzostało wykonane. Innymi słowy, dzieje się tak, gdy wracasz po długiej sesji hackerskiej lub czymkolwiek
innym, gapisz się

Zredagowałem swoje pytanie. Jeśli to możliwe, chciałbym wprowadzić te zmiany do nowego oddziału.
Aswathy P Krishnan,

1
Czasami chcesz tylko odpowiedzi TLDR :)
sachinruk

24

Aby to uprościć, masz dwie opcje ponownego zastosowania skrytki:

  1. git stash pop - Przywróć z powrotem do stanu zapisanego, ale usuwa skrytkę z pamięci tymczasowej.
  2. git stash apply - Przywróć z powrotem do zapisanego stanu i pozostawia listę skrytek do ewentualnego późniejszego ponownego wykorzystania.

Możesz przeczytać bardziej szczegółowo o skrytkach git w tym artykule.


19

Aby sprawdzić zawartość skrytki: -

lista skrytek git

zastosuj określony numer skrytki z listy skrytek: -

git stash Apply stash @ {2}

lub do zastosowania tylko pierwszej skrytki:

git stash pop

Uwaga: git stash pop usunie skrytkę z listy skrytek, podczas gdy git stash nie zostanie zastosowany. Więc używaj ich odpowiednio.


2

Na Macu to działało dla mnie:

lista skrytek git (zobacz wszystkie swoje skrytki)

git stash list

zastosowanie git stash (tylko numer, który chcesz z listy skrytek)

lubię to:

git stash apply 1

0

możesz ukryć niezatwierdzone zmiany za pomocą „git stash”, a następnie przejść do nowego oddziału za pomocą „git checkout -b”, a następnie zastosować ukryte zatwierdzenia „git stash Apply”

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.