Jako dodatkowe wyjaśnienie zwróć uwagę, że git stash
powoduje to dwa lub trzy zatwierdzenia. Wartość domyślna to dwa; otrzymasz trzy, jeśli użyjesz pisowni opcji --all
lub --include-untracked
.
Te dwa lub trzy zatwierdzenia są wyjątkowe pod jednym ważnym względem: nie znajdują się na żadnej gałęzi. Git lokalizuje je za pomocą specjalnej nazwy stash
. 1 Najważniejsze jest jednak to, co Git pozwala - i sprawia, że - robisz z tymi dwoma lub trzema zatwierdzeniami. Aby to zrozumieć, musimy przyjrzeć się temu, co jest w tych zatwierdzeniach.
Co jest w skrytce
Każde zatwierdzenie może zawierać jedno lub więcej zatwierdzeń nadrzędnych . Tworzą one wykres, na którym późniejsze zatwierdzenia wskazują na wcześniejsze. Skrytka normalnie zawiera dwa zatwierdzenia, które lubię wywoływać w i
przypadku zawartości indeksu / obszaru przemieszczania oraz zawartości w
drzewa roboczego. Pamiętaj również, że każde zatwierdzenie zawiera migawkę. W normalnym zatwierdzeniu ten obraz stanu jest tworzony z zawartości indeksu / obszaru przemieszczania. Zatem i
zatwierdzenie jest w rzeczywistości całkowicie normalnym zatwierdzeniem! Po prostu nie ma go na żadnej gałęzi:
...--o--o--o <-- branch (HEAD)
|
i
Jeśli robisz zwykły magazyn, git stash
kod robi to w
teraz, kopiując wszystkie śledzone pliki drzewa roboczego (do tymczasowego indeksu pomocniczego). Git ustawia pierwszego rodzica tego w
zatwierdzenia, aby wskazywał na HEAD
zatwierdzenie, a drugi rodzic, aby wskazywał na zatwierdzenie i
. Na koniec stash
wskazuje na to w
zatwierdzenie:
...--o--o--o <-- branch (HEAD)
|\
i-w <-- stash
Jeśli dodasz --include-untracked
lub --all
, Git wykona dodatkowe zatwierdzenie, u
pomiędzy tworzeniem i
i w
. Zawartością migawki u
są te pliki, które nie są śledzone, ale nie są ignorowane ( --include-untracked
) lub pliki, które nie są śledzone, nawet jeśli są ignorowane ( --all
). Ten dodatkowy u
popełnić ma żadnego rodzica, a następnie, gdy git stash
marki w
, ustawia w
„s trzeciego rodzica tego u
dokonać, aby uzyskać:
...--o--o--o <-- branch (HEAD)
|\
i-w <-- stash
/
u
W tym momencie Git usuwa również wszystkie pliki drzewa roboczego, które znalazły się w u
zatwierdzeniu (używając git clean
do tego).
Przywracanie skrytki
Kiedy idziesz odzyskać skrytkę, możesz jej użyć --index
lub nie. To mówi git stash apply
(lub któregokolwiek z poleceń, które używają wewnętrznie apply
, jak pop
), że powinien on używaći
popełnić próbować zmodyfikować swój aktualny indeks. Ta modyfikacja jest wykonywana za pomocą:
git diff <hash-of-i> <hash-of-i's-parent> | git apply --index
(mniej więcej; jest kilka drobiazgów, które przeszkadzają w realizacji podstawowej idei).
Jeśli pominiesz --index
, git stash apply
całkowicie zignoruje i
zatwierdzenie.
Jeśli skrytka ma tylko dwa zatwierdzenia, git stash apply
może teraz zastosować w
zatwierdzenie. Robi to przez wywołanie git merge
2 (bez zezwalania na zatwierdzenie lub traktowanie wyniku jako normalnego scalania), używając oryginalnego zatwierdzenia, na którym został utworzony schowek ( i
rodzica i w
pierwszego rodzica) jako podstawy scalania, w
jako --theirs
commit, a Twoje aktualne (HEAD) commit jako cel scalenia. Jeśli połączenie się powiedzie, wszystko jest w porządku - cóż, przynajmniej tak uważa Git - i git stash apply
samo się powiedzie. Jeśli git stash pop
używałeś skrytki, kod teraz ją upuszcza . 3 Jeśli scalanie nie powiedzie się, Git deklaruje, że zastosowanie nie powiodło się. Jeśli użyłeśgit stash pop
, kod zachowuje skrytkę i dostarcza ten sam stan błędu, co w przypadku git stash apply
.
Ale jeśli masz trzecie zatwierdzenie - jeśli u
w skrytce, którą stosujesz, jest zatwierdzenie - wszystko się zmienia! Nie ma możliwości udawania, że u
zatwierdzenie nie istnieje. 4 Git nalega na wyodrębnienie wszystkich plików z tego u
zatwierdzenia do bieżącego drzewa roboczego. Oznacza to, że pliki nie mogą w ogóle istnieć lub mieć taką samą zawartość, jak w u
zatwierdzeniu.
Aby to się stało, możesz użyć git clean
siebie - ale pamiętaj, że nieśledzone pliki (zignorowane lub nie) nie istnieją w repozytorium Git, więc upewnij się, że wszystkie te pliki można zniszczyć! Możesz też utworzyć katalog tymczasowy i przenieść tam pliki na przechowanie - lub nawet zrobić inny git stash save -u
lub git stash save -a
, ponieważ będą one działać git clean
za Ciebie. Ale to po prostu pozostawia ci inny u
styl, którym możesz zająć się później.
1 Tak jest w rzeczywistości refs/stash
. Ma to znaczenie, jeśli utworzysz gałąź o nazwie stash
: pełna nazwa gałęzi to refs/heads/stash
, więc nie są one w konflikcie. Ale nie rób tego: Git nie będzie miał nic przeciwko, ale będziesz się mylić. :-)
2git stash
kod faktycznie korzysta git merge-recursive
bezpośrednio tutaj. Jest to konieczne z wielu powodów, a także ma efekt uboczny polegający na tym, że Git nie traktuje tego jako scalenia podczas rozwiązywania konfliktów i zatwierdzania.
3 Dlatego też zalecamy unikanie git stash pop
, na korzyść git stash apply
. Masz szansę przejrzeć, co zostało zastosowane, i zdecydować, czy faktycznie zostało zastosowane poprawnie. Jeśli nie, nadal masz swoją skrytkę, co oznacza, że możesz jej użyć git stash branch
do perfekcyjnego odzyskania wszystkiego. Cóż, zakładając brak tego nieznośnego u
zobowiązania.
4 Naprawdę powinno być: git stash apply --skip-untracked
czy coś. Powinien też istnieć wariant, który oznaczałby upuszczenie wszystkich tych u
plików ze zmianami do nowego katalogu , np git stash apply --untracked-into <dir>
. Być może.
git stash show -p | git apply --3