Close

git stash

Polecenie git stash pozwala tymczasowo „odłożyć na półkę” (lub dodać do schowka) zmiany wprowadzone w kopii roboczej, dzięki czemu możesz zacząć pracę nad czymś innym, a następnie wrócić i ponownie zastosować zmiany. Dodawanie do schowka (stashing) jest przydatne, gdy trzeba szybko zmienić kontekst i rozpocząć pracę nad czym innym, będąc w połowie wprowadzania zmian w kodzie, które nie są jeszcze gotowe do zatwierdzenia.


Dodawanie pracy do schowka


Polecenie git stash pobiera niezatwierdzone zmiany (zarówno zapisane, jak i niezapisane w przechowalni), zapisuje je na potrzeby użycia w przyszłości, a następnie cofa je w kopii roboczej. Przykład:

$ git status
On branch main
Changes to be committed:

    new file:   style.css

Changes not staged for commit:

    modified:   index.html

$ git stash
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage

$ git status
On branch main
nothing to commit, working tree clean
Gałąź Git
materiały pokrewne

Gałąź Git

Logo Bitbucket
POZNAJ ROZWIĄZANIE

Poznaj środowisko Git z rozwiązaniem Bitbucket Cloud

W tym momencie można swobodnie wprowadzać zmiany, tworzyć nowe commity, przełączać gałęzie oraz wykonywać inne operacje Git, a wrócić i ponownie zastosować zmiany ze schowka, gdy wszystko będzie gotowe.

Należy zauważyć, że schowek jest lokalny względem repozytorium Git, a zapisane w nim zmiany nie są przesyłane na serwer podczas wypychania.

Ponowne stosowanie zmian dodanych do schowka


Za pomocą polecenia git stash pop można ponownie zastosować zmiany, które wcześniej zostały dodane do schowka:

$ git status
On branch main
nothing to commit, working tree clean
$ git stash pop
On branch main
Changes to be committed:

    new file:   style.css

Changes not staged for commit:

    modified:   index.html

Dropped refs/stash@{0} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)

Wykonanie operacji „pop” na schowku powoduje usunięcie zmian ze schowka i ponowne zastosowanie ich do kopii roboczej.

Można również ponownie zastosować zmiany do kopii roboczej i jednocześnie zachować je w schowku za pomocą polecenia git stash apply:

$ git stash apply
On branch main
Changes to be committed:

    new file:   style.css

Changes not staged for commit:

    modified:   index.html

Jest ono przydatne, jeśli chcesz zastosować te same zmiany ze schowka w wielu gałęziach.

Znając już podstawy dodawania do schowka, należy pamiętać o pewnym zagrożeniu związanym z korzystaniem z polecenia git stash: domyślnie Git nie dodaje do schowka zmian wprowadzonych w plikach nieśledzonych lub ignorowanych.

Dodawanie do schowka nieśledzonych lub ignorowanych plików


Domyślnie wykonanie polecenia git stash spowoduje dodanie do schowka:

  • zmian, które zostały dodane do indeksu (zmian z przechowalni);
  • zmian wprowadzonych w plikach aktualnie śledzonych przez Git (zmian spoza przechowalni).

Nie spowoduje jednak dodania do schowka:

  • nowych plików w kopii roboczej, które nie zostały jeszcze umieszczone w przechowalni;
  • plików, które zostały zignorowane.

Jeśli więc do naszego przykładu powyżej dodamy trzeci plik, ale nie umieścimy go w przechowalni (tj. nie wykonamy polecenia git add), nie zostanie on dodany do schowka w przypadku użycia polecenia git stash.

$ script.js

$ git status
On branch main
Changes to be committed:

    new file:   style.css

Changes not staged for commit:

    modified:   index.html

Untracked files:

    script.js

$ git stash
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage

$ git status
On branch main
Untracked files:

    script.js

Dodanie opcji -u (lub --include-untracked) pozwala uwzględnić w poleceniu git stash także nieśledzone pliki:

$ git status
On branch main
Changes to be committed:

    new file:   style.css

Changes not staged for commit:

    modified:   index.html

Untracked files:

    script.js

$ git stash -u
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage

$ git status
On branch main
nothing to commit, working tree clean

Można uwzględnić także zmiany wprowadzone w plikach ignorowanych, przekazując opcję -a (lub --all) podczas wykonywania polecenia git stash.

Opcje polecenia „git stash”

Zarządzanie wieloma schowkami


Nie trzeba ograniczać się do jednego schowka. Można wykonać polecenie git stash kilkakrotnie, aby utworzyć wiele schowków, a następnie wyświetlić je za pomocą polecenia git stash list. Domyślnie schowki są oznaczane jako „WIP” (praca w toku) względem gałęzi i commita, na podstawie którego utworzono schowek. Po pewnym czasie trudno jednak zapamiętać, co zawierają poszczególne schowki:

$ git stash list
stash@{0}: WIP on main: 5002d47 our new homepage
stash@{1}: WIP on main: 5002d47 our new homepage
stash@{2}: WIP on main: 5002d47 our new homepage

Aby zapewnić pewien kontekst, dobrze jest dodawać adnotacje z opisem do schowków za pomocą polecenia git stash save "message":

$ git stash save "add style to our site"
Saved working directory and index state On main: add style to our site
HEAD is now at 5002d47 our new homepage

$ git stash list
stash@{0}: On main: add style to our site
stash@{1}: WIP on main: 5002d47 our new homepage
stash@{2}: WIP on main: 5002d47 our new homepage

Domyślnie polecenie git stash pop spowoduje ponowne zastosowanie zmian z ostatnio utworzonego schowka: stash@{0}

Można wybrać schowek, z którego zmiany mają zostać ponownie zastosowane, przekazując jego identyfikator jako ostatni argument, na przykład:

$ git stash pop stash@{2}

Wyświetlanie różnic między schowkami


Można również wyświetlić podsumowanie schowka za pomocą polecenia git stash show:

$ git stash show
 index.html | 1 +
 style.css | 3 +++
 2 files changed, 4 insertions(+)

Przekazanie opcji -p (lub --patch) umożliwia wyświetlenie pełnego zestawu różnic w schowku:

$ git stash show -p
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..d92368b
--- /dev/null
+++ b/style.css
@@ -0,0 +1,3 @@
+* {
+  text-decoration: blink;
+}
diff --git a/index.html b/index.html
index 9daeafb..ebdcbd2 100644
--- a/index.html
+++ b/index.html
@@ -1 +1,2 @@
+<link rel="stylesheet" href="style.css"/>

Częściowe dodawanie zmian do schowka


Można również wybrać dodanie do schowka pojedynczego pliku, kolekcji plików lub poszczególnych zmian z plików. Przekazanie opcji -p (lub --patch) do polecenia git stash spowoduje iteracyjne przejście przez każdy fragment ze zmianami („hunk”) w kopii roboczej z pytaniem, czy ma zostać dodany do schowka:

$ git stash -p
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..d92368b
--- /dev/null
+++ b/style.css
@@ -0,0 +1,3 @@
+* {
+  text-decoration: blink;
+}
Stash this hunk [y,n,q,a,d,/,e,?]? y
diff --git a/index.html b/index.html
index 9daeafb..ebdcbd2 100644
--- a/index.html
+++ b/index.html
@@ -1 +1,2 @@
+<link rel="stylesheet" href="style.css"/>
Stash this hunk [y,n,q,a,d,/,e,?]? n
git stash -p

Naciśnięcie klawisza ? pozwala wyświetlić pełną listę poleceń dotyczących fragmentów ze zmianami. Najczęściej stosuje się następujące z nich:

Polecenie

Opis

/

Opis

wyszukaj fragment ze zmianami za pomocą wyrażenia regularnego

?

Opis

help

n

Opis

nie dodawaj tego fragmentu ze zmianami do schowka

q

Opis

zakończ (wszystkie wybrane dotychczas fragmenty ze zmianami zostaną dodane do schowka)

N

Opis

podziel ten fragment ze zmianami na mniejsze fragmenty

y

Opis

dodaj ten fragment ze zmianami do schowka

Nie ma konkretnego polecenia przerwania operacji, ale użycie skrótu CTRL-C(SIGINT) spowoduje przerwanie procesu dodawania do schowka.

Tworzenie gałęzi na podstawie schowka


Jeśli zmiany w gałęzi będą rozbieżne ze zmianami w schowku, przy próbie ponownego zastosowania zawartości schowka za pomocą polecenia „pop” lub „apply” mogą pojawić się konflikty. Zamiast tego można użyć polecenia git stash branch, aby utworzyć nową gałąź, do której zostaną zastosowane zmiany ze schowka:

$ git stash branch add-stylesheet stash@{1}
Switched to a new branch 'add-stylesheet'
On branch add-stylesheet
Changes to be committed:

    new file:   style.css

Changes not staged for commit:

    modified:   index.html

Dropped refs/stash@{1} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)

To spowoduje wyewidencjonowanie nowej gałęzi w oparciu o commit, z którego utworzono schowek, a następnie wykonanie polecenia „pop” w odniesieniu do schowka.

Oczyszczanie schowka


Jeśli jakiś schowek nie będzie już potrzebny, można go usunąć za pomocą polecenia git stash drop:

$ git stash drop stash@{1}
Dropped stash@{1} (17e2697fd8251df6163117cb3d58c1f62a5e7cdb)

Można również usunąć wszystkie schowki, używając następującego polecenia:

$ git stash clear

Sposób działania polecenia „git stash”


Jeśli interesował Cię wyłącznie sposób użycia polecenia git stash, możesz przerwać czytanie w tym miejscu. Jeśli jednak chcesz się dowiedzieć, jak dokładnie działa Git (i polecenie git stash), czytaj dalej!

Schowki są w rzeczywistości zakodowane w repozytorium jako obiekty commitów. Specjalna referencja w lokalizacji .git/refs/stash wskazuje na ostatni utworzony schowek, a do wcześniej utworzonych schowków można odwołać się za pośrednictwem dziennika reflog referencji stash. Dlatego do schowków odwołujesz się za pomocą ciągu stash@{n}: w istocie oznacza to odwołanie do n-tej pozycji w dzienniku reflog referencji stash. Schowek jest po prostu commitem, dlatego można go sprawdzić za pomocą polecenia git log:

W zależności od rodzaju zawartości dodawanej do schowka, pojedyncza operacja git stash powoduje utworzenie dwóch lub trzech nowych commitów. Na powyższym diagramie przedstawiono następujące commity:

  • stash@{0} — nowy commit do przechowywania śledzonych plików, które znajdowały się w kopii roboczej w momencie wykonania polecenia git stash.
  • Pierwszy element nadrzędny commita stash@{0} — istniejący wcześniej commit, na który w momencie wykonania polecenia git stash wskazywał wskaźnik HEAD.
  • Drugi element nadrzędny commita stash@{0} — nowy commit reprezentujący indeks w momencie wykonania polecenia git stash.
  • Trzeci element nadrzędny commita stash@{0}— nowy commit reprezentujący nieśledzone pliki, które w momencie wykonania polecenia git stash znajdowały się w kopii roboczej. Ten trzeci element nadrzędny jest tworzony tylko wówczas, gdy:
    • kopia robocza faktycznie zawierała nieśledzone pliki;
    • oraz użyto opcji --include-untracked lub --all podczas wywoływania polecenia git stash.

Sposób kodowania drzewa roboczego i indeksu jako commitów po użyciu polecenia git stash:

  • Przed dodaniem do schowka drzewo robocze może zawierać zmiany wprowadzone w plikach śledzonych, nieśledzonych i ignorowanych. Niektóre z tych zmian mogą być również przechowywane w indeksie.
Przed dodaniem do schowka
  • Wywołanie polecenia git stash koduje wszelkie zmiany w śledzonych plikach jako dwa nowe commity w grafie DAG: jeden dla zmian poza przechowalnią i jeden dla zmian przechowywanych w indeksie. Specjalna referencja refs/stash zostanie zaktualizowana tak, aby je wskazywała.
git stash
  • Użycie opcji --include-untracked pozwala również zakodować wszelkie zmiany w nieśledzonych plikach jako dodatkowy commit.
git stash --include-untracked
  • Z kolei opcja --all umożliwia uwzględnienie zmian wprowadzonych we wszystkich ignorowanych plikach wraz ze zmianami w plikach nieśledzonych w tym samym commicie.
git stash --all

Po wykonaniu polecenia git stash pop kopia robocza oraz indeks są aktualizowane o zmiany z powyższych commitów, a dziennik reflog schowka jest modyfikowany w celu usunięcia commita zastosowanego za pomocą polecenia „pop”. Warto pamiętać, że commity zastosowane za pomocą polecenia „pop” nie są usuwane od razu, tylko stają się kandydatami do późniejszego usuwania zbędnych elementów.


Udostępnij ten artykuł
Następny temat

Zalecane lektury

Dodaj te zasoby do zakładek, aby dowiedzieć się więcej na temat rodzajów zespołów DevOps lub otrzymywać aktualności na temat metodyki DevOps w Atlassian.

Ludzie współpracujący przy ścianie pełnej narzędzi

Blog Bitbucket

Ilustracja DevOps

Ścieżka szkoleniowa DevOps

Demonstracje funkcji z ekspertami Atlassian

Zobacz, jak Bitbucket Cloud współpracuje z Atlassian Open DevOps

Zapisz się do newslettera DevOps

Thank you for signing up