Jak odzyskać ukryte niezarejestrowane zmiany

Miałem kilka niezarejestrowanych zmian w mojej gałęzi deweloperskiej i schowałem je za pomocą git stash, ale były pewne zmiany, które były bardzo ważne wśród tych schowanych. Czy jest jakiś sposób na przywrócenie tych zmian?

Od tego czasu wprowadziłem również pewne zmiany na plikach z ukrytym kodem.

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

 437
Author: Flimzy, 2013-09-25

3 answers

Łatwa odpowiedź na proste pytanie to git stash apply

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

Po skończeniu zmian - apply wygląda dobrze i jesteś pewien, że nie potrzebujesz już skrytki - następnie użyj git stash drop, aby się go pozbyć.

Zawsze sugeruję użycie git stash apply zamiast git stash pop. Różnica polega na tym, że apply zostawia skrytkę wokół dla łatwego ponownego wypróbowania apply, lub dla patrząc na itp. Jeśli {[13] } jest w stanie wydobyć skrytkę, natychmiast również drop ją, a jeśli nagle zdasz sobie sprawę, że chcesz wydobyć ją gdzieś indziej (w innej gałęzi), lub z --index, lub czymś takim, to nie jest takie proste. Jeśli apply, ty możesz wybrać kiedy drop.

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


What if robisz bardziej zaawansowane czy bardziej skomplikowane rzeczy?

Istnieją co najmniej trzy lub cztery różne "sposoby użycia Git stash". Powyższe odnosi się do" ścieżki 1","łatwej ścieżki":

  1. Zacząłeś od czystej gałęzi, pracowałeś nad pewnymi zmianami, a potem zdałeś sobie sprawę, że robisz je w złej gałęzi. Po prostu chcesz wziąć zmiany, które masz teraz i "przenieść" je do innej gałęzi.

    Jest to prosty przypadek, opisany powyżej. Run git stash save (or plain git stash, to samo). Sprawdź drugą gałąź i użyj git stash apply. Dzięki temu git połączy się z Twoimi wcześniejszymi zmianami, używając dość potężnego mechanizmu scalania. sprawdź dokładnie wyniki (z git diff), aby zobaczyć, czy ci się podobają, a jeśli Tak, użyj git stash drop, aby upuścić skrytkę. Jesteś skończony!

  2. Zacząłeś pewne zmiany i Ukryłeś je. Potem przełączyłeś się na inną gałąź i zacząłeś kolejne zmiany, zapominając, że masz schowane.

    Teraz chcesz aby zachować, a nawet przenieść, te zmiany, i zastosuj również swój Schowek.

    Możesz w rzeczywistości git stash save ponownie, ponieważ git stash tworzy "stos" zmian. Jeśli to zrobisz, masz dwa znaki, jeden o nazwie stash - ale możesz również napisać stash@{0} - i jeden pisany stash@{1}. Użyj git stash list (w dowolnym momencie), aby zobaczyć je wszystkie. Najnowszy jest zawsze najniższy. Kiedy git stash drop, spada najnowszy, a ten, który był stash@{1}, przechodzi na szczyt stosu. Gdybyś miał jeszcze więcej, ten to było stash@{2} staje się stash@{1}, i tak dalej.

    Możesz apply, a następnie drop także konkretny Schowek: git stash apply stash@{2} i tak dalej. Upuszczając określony zapas, zmienia numerację tylko tych wyżej ponumerowanych. Ponownie, ten bez numeru jest również stash@{0}.

    Jeśli zgromadzisz dużo zapasów, może być dość bałagan (czy towar chciałem stash@{7} czy był {38]}? Chwila, właśnie nacisnąłem kolejny, teraz są 8 i 5?). Ja osobiście wolę przenieść te zmiany do nowego oddziału, ponieważ oddziały mają imiona, a cleanup-attempt-in-December znaczy dla mnie o wiele więcej niż stash@{12}. (Polecenie git stash pobiera opcjonalny save-message, a to może pomóc, ale jakoś wszystkie moje blokady kończą się nazwami WIP on branch.)

  3. (Extra-advanced) użyłeś git stash save -p, lub ostrożnie git add-ed i/lub git rm-ed określonych bitów kodu przed uruchomieniem git stash save. Jedna wersja była przechowywana w magazynie Indeks/staging, a druga (Inna) w drzewie roboczym. Chcesz to wszystko zachować. Więc teraz ty użyj git stash apply --index, a to czasem zawodzi z:

    Conflicts in index.  Try without --index.
    
  4. Używasz git stash save --keep-index, aby przetestować "co zostanie popełnione". Ta odpowiedź wykracza poza zakres tej odpowiedzi; zobacz inną odpowiedź StackOverflow.

W skomplikowanych przypadkach, polecam zacząć od" czystego " katalogu roboczego, zatwierdzając wszelkie zmiany, które masz teraz (w nowej gałęzi, jeśli chcesz). W ten sposób "gdzieś", które je stosujesz, nie ma nic innego w to, i będziesz tylko próbował ukrytych zmian:

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 bardziej 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 "stash" to commit, to tylko nieco" zabawny/dziwny "commit, który nie jest "na gałęzi". Operacja apply sprawdza, co zmienił commit i próbuje go powtórzyć gdziekolwiek jesteś teraz. Schowek nadal tam będzie (apply trzyma go w pobliżu), więc możesz spojrzeć na niego więcej lub zdecydować to było złe miejsce, żeby spróbować jeszcze raz.


Za każdym razem, gdy masz skrytkę, możesz użyć git stash show -p, aby zobaczyć uproszczoną wersję tego, co znajduje się w skrytce. (Ta uproszczona wersja patrzy tylko na zmiany "ostatecznego drzewa pracy", Nie zapisany indeks zmienia się, który --index jest przywracany oddzielnie.) Polecenie git stash apply, Bez --index, próbuje teraz wprowadzić te te same zmiany w Twoim katalogu roboczym.

To prawda, nawet jeśli Mam już pewne zmiany. Polecenie apply chętnie stosuje stash do zmodyfikowanego katalogu roboczego (a przynajmniej próbuje go zastosować). Można, 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 wybrać kolejność "apply" tutaj, wybierając poszczególne stasze do zastosowania w określonej kolejności. Zauważ jednak, że za każdym razem robisz "Git merge" i jak ostrzega dokumentacja merge:

Uruchamianie git merge z nietrywialnymi zmianami jest zniechęcony: o ile jest to możliwe, może pozostawić cię w stanie, który jest trudny wycofać się w razie konfliktu.

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


A co z najgorszym możliwy przypadek?

Załóżmy, że robisz wiele zaawansowanych rzeczy z Gitem, i stworzyłeś skrytkę i chcesz git stash apply --index, ale nie jest już możliwe zastosowanie zapisanej skrytki z --index, ponieważ gałąź zbytnio się rozeszła od czasu, kiedy ją zapisałeś.

Po to jest git stash branch.

Jeśli:

  1. sprawdź dokładny commit byłeś na kiedy zrobiłeś oryginalny stash, a następnie
  2. Utwórz nową gałąź i wreszcie
  3. git stash apply --index

Próba odtworzenia zmian zdecydowaniezadziała. To właśnie robi git stash branch newbranch. (A następnie upuszcza zapas, ponieważ został pomyślnie zastosowany.)


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

To, co robi --index jest proste do wyjaśnienia, ale trochę skomplikowane wewnętrznie:
  • kiedy masz zmiany, musisz git add (lub "etap") je przed commit ing.
  • Tak więc, kiedy uruchomiłeś git stash, mogłeś edytować oba pliki foo i zorg, ale tylko zainscenizowałeś jeden z nich.
  • więc Kiedy poprosisz o odzyskanie towaru, może być miło, jeśli git add jest to added rzeczy i robi Nie git add nie dodanych rzeczy. Oznacza to, że jeśli add ed foo, ale nie zorg przed wykonaniem stash, może być miło mieć dokładnie taką samą konfigurację. To, co było wystawione, powinno być ponownie wystawione; to, co zostało zmodyfikowane, ale nie wystawione, powinno być ponownie zmodyfikowane, ale nie wystawione.

Flaga --index do apply próbuje ustawić rzeczy w ten sposób. Jeśli twoje drzewo pracy jest czyste, to zwykle po prostu działa. Jeśli jednak twoje drzewo pracy ma już rzeczy added, możesz zobaczyć, jak mogą tu być pewne problemy. Jeśli pominiesz --index, operacja apply nie podejmie próby zachowania całej konfiguracji staged/unstaged. Zamiast tego, po prostu wywołuje mechanizm scalania Gita, używając commita drzewa roboczego w "stash bag" . Jeśli nie dbałość o zachowanie staged/unstaged, pomijanie --index sprawia, że o wiele łatwiej jest git stash apply robić swoje.

 727
Author: torek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:15
git stash pop

Wszystko wróci na swoje miejsce

Jak sugerowano w komentarzach, możesz użyć git stash branch newbranch, Aby zastosować stash do nowej gałęzi, która jest taka sama jak running:

git checkout -b newbranch
git stash pop
 37
Author: Stefano Falasca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-14 08:35:42

Aby to uprościć, masz dwie opcje, aby ponownie zastosować swój schowek:

  1. git stash pop - przywraca stan zapisany, ale usuwa skrytkę z tymczasowego magazynu.
  2. git stash apply - Przywróć stan zapisany i pozostawia listę skrytek do późniejszego ponownego użycia.

Możesz przeczytać bardziej szczegółowo o Git stashes w tym artykule.

 5
Author: Nesha Zoric,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-25 07:49:29