Jak odblokować tylko niektóre pliki?

385

Ukryłem swoje zmiany. Teraz chcę rozpakować tylko niektóre pliki ze skrytki. W jaki sposób mogę to zrobić?

Morfeusz
źródło
4
Myślę, że musisz zastosować całą skrytkę, ale wtedy możesz selektywnie ponownie schować.
Richard
4
@AbdouTahiri Co jest nie tak ze skrytką?
alex
32
@AbdouTahiri Uhhhh .. git stash jest legalną funkcją i niezwykle przydatną. Używam tego codziennie. Powiedzmy, że współpracownik potrzebuje mojej recenzji, ale jestem w trakcie złożonego zestawu zmian. Nie zamierzam zatwierdzać stosu zepsutego kodu tylko po to, by móc zmieniać gałęzie. Zamierzam ukryć, zamienić gałęzie, przejrzeć, przełączyć z powrotem, odblokować. Czy zastanawiasz się nad tym, kto lub dlaczego skrytka git jest rzekomo „nie zalecana”? To, że twoja historia gitów jest zamazana i trudna do odczytania, nie oznacza, że ​​wszyscy są inni. Brudny zestaw skrytek git to po prostu zły przepływ pracy, a nie wada Gita.
dudewad
6
@alex Nic. Nic nie jest nie tak z Git Stash. Nadal go używaj.
dudewad

Odpowiedzi:

460

Jak wspomniano poniżej i szczegółowo opisano w „ Jak wyodrębnić pojedynczy plik (lub zmiany w pliku) z skrytki git? ”, Możesz zastosować użycie git checkoutlub git showprzywrócić określony plik.

git checkout stash@{0} -- <filename>

To powoduje nadpisywanie filename : upewnij się, że nie masz lokalnych modyfikacji, albo możesz zamiast tego scalić ukryty plik .

(Jak skomentował przez Jaime M. , dla niektórych muszli jak tcsh, gdzie trzeba uciec znaków specjalnych, składnia będzie: git checkout 'stash@{0}' -- <filename>)

lub aby zapisać go pod inną nazwą pliku:

git show stash@{0}:<full filename>  >  <newfile>

(zwróć uwagę, że tutaj <full filename>jest pełna ścieżka do pliku w stosunku do górnego katalogu projektu (pomyśl: w odniesieniu do stash@{0})).

Yumper sugeruje w komentarzach :

Jeśli chcesz ręcznie wybrać zmiany, które chcesz zastosować z tego pliku:

git difftool stash@{0}..HEAD -- <filename>

Vivek dodaje w komentarzach :

Wygląda na to, że „ git checkout stash@{0} -- <filename>” przywraca wersję pliku z momentu wykonania skrytki - NIE stosuje (tylko) ukrytych zmian dla tego pliku.
Aby zrobić to drugie:

git diff stash@{0}^1 stash@{0} -- <filename> | git apply

(jak skomentował przez peterflynn , może być konieczne | git apply -p1w niektórych przypadkach usunięcie jednego ( p1) prowadzącej ukośnik od tradycyjnych ścieżek różnice)


Jak skomentowano: „unstash” ( git stash pop), a następnie:

  • dodaj to, co chcesz zachować do indeksu ( git add)
  • schować resztę: git stash --keep-index

Ostatni punkt pozwala zachować niektóre pliki podczas ukrywania innych.
Ilustruje to „ Jak ukryć tylko jeden plik z wielu plików, które uległy zmianie ”.

VonC
źródło
5
To nie działa, jeśli nie możesz z git stash poppowodu konfliktu plików. Odpowiedź Balamurugana A pomogła mi w tym przypadku.
Andrey
1
Jeśli chcesz ręcznie wybrać zmiany, które chcesz zastosować z tego pliku, możesz użyć skrytki git difftool @ {0} .. HEAD - <nazwa_pliku>
yucer
5
Wygląda na to, że „git Checkout stash @ {0} - <nazwa pliku>” przywraca wersję pliku z momentu wykonania skrytki - NIE stosuje (tylko) ukrytych zmian dla tego pliku. Aby to zrobić: „git diff stash @ {0} ^ 1 stash @ {0} - <nazwa_pliku> | git stosuje się”
Vivek
1
@JaimeM. Dziękuję Ci. W odpowiedzi umieściłem twój komentarz dla większej widoczności.
VonC
1
Zakładając, że unstashoznacza to pop, jak mi się wydaje, że w większości przypadków prawdopodobnie tak by było, to tylko częściowo odpowiada na pytanie. Jak następnie usunąć selektywnie zastosowane elementy ze skrytki, aby uniknąć późniejszych konfliktów i / lub zamieszania podczas usuwania pozostałych zmian?
DylanYoung
115
git checkout stash@{N} <File(s)/Folder(s) path> 

Na przykład. Aby przywrócić tylko plik ./test.c i folder ./include z ostatniego składowania,

git checkout stash@{0} ./test.c ./include
Balamurugan A.
źródło
12
To poprawna odpowiedź! Jednoliniowe polecenie, aby zastosować tylko ukryte zmiany z określonych plików, działa jak urok!
poziomy
1
Aby zastosować (tylko) ukryte zmiany w pliku: „git diff stash @ {N} ^ 1 skrytka {{N} - <nazwa pliku> | git Apply”
Vivek
To też działa dla mnie. Po prostu wybiórczo kasuj pliki potrzebne do skasowania i gotowe. Utknąłem w tym i użyłem -aflagi podczas tworzenia skrytki.
Rajeev Ranjan
1
@ 4levels Myślę, że „zastosowanie ukrytych zmian” nie jest tym, co się dzieje, prawda? Wydaje mi się, że „nadpisuj wszystko, co masz, kopią ze skrytki”.
msouth
35

Myślę, że odpowiedź VonC jest prawdopodobnie tym, czego chcesz, ale oto sposób na selektywne „zastosuj git”:

git show stash@{0}:MyFile.txt > MyFile.txt
Mike Monkiewicz
źródło
4
W niektórych przypadkach może to być pożądane, ale należy pamiętać, że to polecenie zastąpi, a nie scali ze zmianami katalogu roboczego.
Rhubbarb,
To działa dla mnie, ponieważ chciałem po prostu skopiować plik, który istnieje tylko w skrytce i nic mnie to nie obchodziło checkout.
Tom Russell
1
W przypadku Windows PowerShell: git show stash@`{0`}:Path/To/MyFile.txt |sc Path/To/MyFile.txt- backsticks są konieczne, aby PS nie interpretował specjalnie nawiasów klamrowych, i scjest to konieczne, ponieważ >operator PS domyślnie przyjmuje UTF-16 (właściwie UCS-2), co prawdopodobnie nie jest tym, czego chcesz. Odpowiedź @Balamurugan A nie cierpi z powodu tych problemów.
Ian Kemp,
19

Najpierw wypisz wszystkie skrytki

git stash list

stash@{0}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{1}: WIP on Produktkonfigurator: 132c06a5 Cursor bei glyphicon plus und close zu zeigende Hand ändern
stash@{2}: WIP on master: 7e450c81 Merge branch 'Offlineseite'

Następnie pokaż, które pliki są w skrytce (wybierzmy skrytkę 1):

git stash show 1 --name-only

//Hint: you can also write
//git stash show stash@{1} --name-only

 ajax/product.php
 ajax/productPrice.php
 errors/Company/js/offlineMain.phtml
 errors/Company/mage.php
 errors/Company/page.phtml
 js/konfigurator/konfigurator.js

Następnie zastosuj plik, który chcesz:

git checkout stash@{1} -- <filename>

lub cały folder:

git checkout stash@{1} /errors

Działa również bez, --ale zaleca się ich użycie. Zobacz ten post.

Konwencjonalne jest również uznawanie podwójnego myślnika za sygnał do zatrzymania interpretacji opcji i traktowania wszystkich następujących argumentów dosłownie.

czarny
źródło
1
Dzięki tej edycji jest to wyraźniejsze. +1
VonC
1
Próbowałem na wiele sposobów i właśnie tego potrzebowałem. Stałem przed problemem, który git stash popzgłosił błąd dotyczący nieśledzonych plików. Dziękuję Ci.
Ramin Firooz,
10

Jeśli ty git stash pop(bez konfliktów) usunie skrytkę po jej zastosowaniu. Ale jeśli git stash applyzastosujesz łatkę bez usuwania jej z listy skrytek. Następnie możesz cofnąć niechciane zmiany za pomocągit checkout -- files...

Ben Jackson
źródło
2
Aby wyjaśnić konflikty w części tego postu, jeśli Ty git stash popi tam JESTEŚ konflikty, będziesz musiał je naprawić ręcznie, a skrytka NIE zostanie usunięta.
Thomas McCabe
6

Jeszcze jeden sposób:

git diff stash@{N}^! -- path/to/file1 path/to/file2  | git apply -R
Lacho Tomov
źródło
2
To jedyna poprawna odpowiedź IMO. Użycie checkoutlub showspowoduje zastąpienie pliku na ślepo zamiast po prostu wprowadzania zmian. „Jeszcze jeden sposób” to mało powiedziane.
kambuzowy
1
Nie otrzymuję tego, path/to/file2co chcesz odróżnić od tego samego pliku w obszarze roboczym. Wyjście z drugiej ścieżki działa dla mnie dobrze. - I pojawia się komunikat o błędzie przy użyciu -Ropcji („zastosować łatkę w odwrotnej kolejności”, próbując załatać ukrytą wersję ?!). Tak wygląda moja działająca wersja git diff stash@{N}^! -- path/to/file | git apply -.
ThomasH
„łatka nie powiodła się”? Wypróbuj połączenie 3-kierunkowe. ...| git apply -3 -
John Mee
6

Dla użytkowników systemu Windows: nawiasy klamrowe mają specjalne znaczenie w programie PowerShell. Możesz albo otoczyć pojedyncze cudzysłowy, albo uciec za pomocą backsticka. Na przykład:

git checkout 'stash@{0}' YourFile

Bez tego może pojawić się błąd:

Unknown switch 'e'

Janac Meena
źródło
3
Pełne oceny w programie PowerShell za najmniej pomocny komunikat użytkownika, jaki widziałem w tym miesiącu.
holdenweb,