'git stash apply' w trybie interaktywnym

Mam serie plików do schowka (stash{0}) i chciałbym git apply tylko niektóre części / fragmenty tych plików(zwykle znane jako Tryb interaktywny ).

Czy to możliwe?

Widziałem, że można wykonać

git stash save -p 'Stash name'

Ale wydaje się, że nie jest to możliwe

git stash apply -p 'Stash name'
Wiesz jak to osiągnąć?
Author: Kamafeather, 2015-01-28

4 answers

Czy to możliwe?

Tak jest!
git checkout -p stash@{0}

Gdzie możesz zastąpić 0 w stash@{0} indeksem skrytki, którą chcesz zastosować.

Użyj git stash list i git show -p stash@{n} jeśli nie jesteś pewien, który n jest skrytką, którą chcesz zastosować.

Nie zapomnij git stash drop stash@{n} Kiedy wiesz, że nie potrzebujesz już tego schowka, ponieważ git checkout oczywiście nie upuści go dla Ciebie.

Dlaczego to działa?

Kluczem jest uświadomienie sobie, że staśki są w istocie, odwołuje się do commity tak jak znaczniki i gałęzie.

W rzeczy samej, są one przechowywane w .git/refs/stash, jednej linii na hash skrytki.

Caveats

Jak @mgadda wspomniano w komentarzach poniżej, git checkout -p próbuje zastosować całą różnicę między zatwierdzeniem a bieżącą przestrzenią roboczą.

W przypadku Git stash, jeśli skrytka, którą próbujesz zastosować, została wykonana przeciwko innemu zatwierdzeniu, to git checkout -p stash@{n} spróbuje zastosować interaktywnie wszystkie różnice między zatwierdzeniem stash@{n} a zatwierdzeniem bieżącej przestrzeni roboczej, łącznie ze wszystkimi zatwierdzeniami nadrzędnymi, które są różne .

Na przykład, jeśli próbujesz zastosować skrytkę, która została zapisana "wiele commitów temu" w bieżącym obszarze roboczym, git checkout -p stash@{n} spróbuje zastosować nie tylko zmiany w skrytce, ale także spróbuje przywrócić wszystkie zmiany, które zaszły pomiędzy zatwierdzeniem, na którym skrytka jest oparta, a aktualnym zatwierdzeniem.

Odwrotnie, jeśli próbujesz zastosować skrytkę "z przyszłości", tzn. do gałęzi, która jest liczbą commitów sprzed zatwierdzenia, na którym skrytka jest oparta, to git checkout -p stash@{n} spróbuje również zastosować wszystkie inne zmiany, które zaszły między aktualnym zatwierdzeniem a zatwierdzeniem z przyszłości, oprócz zmian z samego skrytki.

(jeśli się zastanawiasz, git checkout -p stash@{n} skrytka z gałęzi równoległej spróbuje przywrócić wszystkie zmiany pomiędzy aktualnym zatwierdzeniem a oryginalnym punktem rozgałęzienia i stosują również wszystkie zmiany między punktem rozgałęzienia a drugą gałęzią, oprócz zmiany w skrytce).

Obejścia

Istnieje kilka obejść, żaden z nich nie jest idealny dla każdej sytuacji:]}
    1. bądź bardzo ostrożny z plastrami, które akceptujesz, kiedy to robisz git checkout -p stash@{n}
    1. zrób git stash pop, a następnie git stash Jeszcze raz przed git checkout -p .... Ale jeśli chcesz zrobić częściowe zastosowanie skrytki, aby uniknąć konfliktów, to nie pomoże. W takim przypadku patrz rozwiązanie 4 poniżej.
    1. Jeśli masz graficzne narzędzie różnicujące obsługiwane przez git (jak meld ), możesz użyć git difftool i "zastosować w lewo" tylko zmiany, które Cię interesują:

      • git difftool -d stash@{n} aby porównać cały schowek i wszystkie jego pliki

      • git difftool stash@{n} -- path/to/file aby porównać pojedynczy plik

    1. (na podstawie odpowiedzi @ Andrzej) na odłączona Głowa, wróć do commitu "rodzica" interesującego cię skrytki, zastosuj skrytkę, ponownie Schowaj interaktywnie tylko te części, które Cię interesują, wróć i ponownie zastosuj mniejszy skrytkę.

Krok po kroku:

git checkout stash@{n}^  # notice the "^". 

# Now you're in a detached head in the parent commit of the stash.
# It can be applied cleanly:
git stash apply stash@{n}

# Now save only the diffs you're interested in:
git stash -p

# remove the rest of the old stash
git checkout -- .  # be careful or you could remove unrelated changes

# go back to the branch where you want to apply the smaller stash
git checkout <my previous branch>

# apply the smaller stash
git stash pop
 66
Author: LeoRochael,
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-07-20 19:52:18

To, co często robię (w Git bash) to

git stash show -p 'stash@{0}' >tmp.patch

Następnie edytuję plik i usuwam części, których nie chcę. Wreszcie mówię

<tmp.patch git apply

Lub

<tmp.patch patch -p1

Nie działa to jednak w przypadku plików binarnych, ale akceptowana odpowiedź (używając checkOut-p)również nie działa.

 6
Author: user829755,
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
2019-12-18 08:18:58

Jednym z możliwych sposobów jest zresetowanie indeksu, a następnie użycie interaktywnego add

# 0. ensure there are no uncommitted changes
git status

# 1. apply a changeset as is
git stash apply stash@{n}
# ... fix or discard conflicts if any

# 2. reset the index 
git reset

# 3. interactively add the required chunks (except new files)
git add -p

# 4. stash all other changes
git stash save --keep-index "comment"
# 4. or just discards all other changes in the working tree
git checkout-index -f -a

# 5. commit
git commit -m "comment"

Innym sposobem jest użycie interaktywnego resetu zamiast interaktywnego dodawania.

# 0. ensure the working tree does not have unstaged changes
git status

# 1. apply a changeset as is
git stash apply stash@{n}
# ... fix or discard conflicts if any

# 2. interactively exclude the unneeded chunks from the index 
git reset -p

# 3. stash all other changes
git stash save --keep-index "comment"
# 3. or just discards all other changes in the working tree
git checkout-index -f -a

# 4. commit
git commit -m "comment"
 3
Author: ruvim,
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-09-05 13:22:22

Myślę, że nie ma sposobu, aby zastosować zmiany przez hunks (lub nawet przez plik). Będziesz musiał zastosować skrytkę, a następnie ukryć zmiany, których nie chcesz interaktywnie(za pomocą git stash save -p). Jeśli obawiasz się konfliktów, możesz najpierw ukryć niezakontraktowane zmiany, zastosować skrytkę, ukryć sprzeczne fragmenty, a następnie zastosować drugą skrytkę.

 1
Author: Andrew,
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-03-04 11:18:53