git stash -> scal ukrytą zmianę z bieżącymi zmianami


186

Wprowadziłem kilka zmian w moim oddziale i zdałem sobie sprawę, że zapomniałem o innych niezbędnych zmianach w tym oddziale. To, czego chcę, to sposób na połączenie moich ukrytych zmian z bieżącymi zmianami.

Czy jest na to sposób?

To bardziej dla wygody, w końcu poddałem się i popełniłem najpierw moje obecne zmiany, a potem moje ukryte zmiany, ale wolałbym je wprowadzić za jednym zamachem.


Prawdopodobnie duplikat stackoverflow.com/q/1360712/72178
ks1322

odpowiedź Jozuego powinna być zaakceptowaną odpowiedzią. Ten post stackoverflow jest pierwszym linkiem Google do tego pytania, udziel prawidłowej odpowiedzi w Internecie!
Jérôme,

Odpowiedzi:


271

Właśnie odkryłem, że jeśli twoje niezaangażowane zmiany zostaną dodane do indeksu (tzn. „Przeniesione”, używając git add ...), wtedy git stash apply(i przypuszczalnie git stash pop) faktycznie wykona prawidłowe scalenie. Jeśli nie ma konfliktów, jesteś złoty. Jeśli nie, rozwiąż je jak zwykle git mergetoolza pomocą edytora lub ręcznie.

Dla jasności, oto proces, o którym mówię:

mkdir test-repo && cd test-repo && git init
echo test > test.txt
git add test.txt && git commit -m "Initial version"

# here's the interesting part:

# make a local change and stash it:
echo test2 > test.txt
git stash

# make a different local change:
echo test3 > test.txt

# try to apply the previous changes:
git stash apply
# git complains "Cannot apply to a dirty working tree, please stage your changes"

# add "test3" changes to the index, then re-try the stash:
git add test.txt
git stash apply
# git says: "Auto-merging test.txt"
# git says: "CONFLICT (content): Merge conflict in test.txt"

... prawdopodobnie tego szukasz.


tl; dr

Uruchom git addpierwszy.


8
Taki hack, ale hej, to działa i wydaje się, że jest to jedyny sposób, aby to zrobić. Chciałbym, żeby coś było git stash apply --force.
Matt Kantor,

12
W rzeczywistości nie jest to hack - to ulepszenie w stosunku do tego, czego chcesz, ponieważ możesz łatwo powrócić do zmian w indeksie.
hoffmanc

2
Wow, czy to zachowanie jest naprawdę zamierzone przez git?
edi9999

9
Nie sądzę, żeby Git miał coś „zamierzonego”. Mam przeczucie, że cokolwiek to robi, robi to przez przypadek.
Profpatsch,

5
To idealne rozwiązanie. Właśnie tak zrobiłem git add ., git stash applya następnie git resetzastosowałem skrytkę do moich zmian roboczych i scaliłem bez konieczności dokonywania zatwierdzeń.
Stephen Smith

70

Uruchamianie git stash poplub git stash applyjest zasadniczo połączeniem. Nie powinieneś potrzebować zatwierdzać bieżących zmian, chyba że pliki zmienione w skrytce zostaną również zmienione w kopii roboczej, w takim przypadku zobaczysz ten komunikat o błędzie:

error: Your local changes to the following files would be overwritten by merge:
       file.txt
Please, commit your changes or stash them before you can merge.
Aborting

W takim przypadku nie można zastosować skrytki do bieżących zmian w jednym kroku. Możesz zatwierdzić zmiany, zastosować skrytkę, zatwierdzić ponownie i zmiażdżyć te dwa zatwierdzenia używając, git rebasejeśli naprawdę nie chcesz dwóch zatwierdzeń, ale może to być bardziej kłopotliwe niż warte.


1
Dostałem ten komunikat - zmiany nie powodują konfliktu, ale współużytkują te same pliki, w dowolnym miejscu za pomocą skrytek / aplikacji?
Bemis,

1
Przepraszam, to miałem na myśli przez „scalanie konfliktów”, ale to był zły wybór słów. Myślę, że ten komunikat o błędzie jest dość ostateczny: jeśli pliki zmienione w kopii roboczej zostaną również zmienione w skrytce, nie można zastosować skrytki. Zaktualizowałem swoją odpowiedź możliwym obejściem.
Brandan

3
Nie uważałbym tego za odpowiedź we wszystkich przypadkach. Być może ukryłeś tylko część zestawu zmian w określonym pliku, ponieważ chciałeś coś przetestować podczas programowania. I możesz nie chcieć zatwierdzać bieżącej zawartości pliku w tym momencie (lub wcale), ponieważ jest to WIP. To prawdziwy problem z gitem, że ukrytych zmian nie można scalić z obecnym oddziałem
Thomas Watson

21
Odpowiedź Joshua Warnera powinna być taka, jak oznaczono jako poprawną. Aby scalić skrytkę, przygotuj zmiany, zastosuj skrytkę, rozwiąż wszelkie konflikty, a następnie (w razie potrzeby) wycofaj zmiany.
Vroo

4
„Możesz zatwierdzić zmiany, zastosować ukrywanie, zatwierdzić ponownie i zmiażdżyć te dwa zatwierdzenia za pomocą git rebase, jeśli naprawdę nie chcesz dwóch zatwierdzeń, ale może to być bardziej kłopotliwe niż warte”. Zamiast tego możesz: Zatwierdź zmiany, zastosuj skrytkę, a następnie git commit --amend.
gabe

27

To, czego chcę, to sposób na połączenie moich ukrytych zmian z bieżącymi zmianami

Oto kolejna opcja, aby to zrobić:

git stash show -p|git apply
git stash drop

git stash show -ppokaże łatkę ostatnio zapisanej skrytki. git applyzastosuje to. Po zakończeniu scalania scaloną skrytkę można upuścić git stash drop.


1
Dzięki za to - nie wiem, dlaczego git stash popnie robi tego tylko w przypadkach, w których scalanie ma zastosowanie ...
Iguananaut

Wersja rozszerzona: git stash show -p --no-color | git apply --3way( --3way= cofnij się na łączeniu 3-kierunkowym, jeśli poprawka się nie powiedzie).
DmitrySandalov,

Ale git stash show -ptworzy różnicę między ukrytą zawartością a zatwierdzeniem z powrotem, gdy wpis skrytki został utworzony po raz pierwszy . Tak więc zastąpiłoby to zmiany pliku roboczego wprowadzone przez OP.
Paul F. Wood

Po co nadpisywać? Wytworzony plik różnicowy git stash show -pzostanie scalony przez git apply, jeśli będzie to możliwe bez konfliktów.
ks1322

1

W ten sposób git addnajpierw to robię git stash apply <stash code>. To najprostszy sposób.


3
Jak to nie jest dokładna kopia tl; dr zaakceptowanej odpowiedzi?
RomainValeri

0

Jak sugeruje @Brandan, oto, co musiałem zrobić, aby się obejść

error: Your local changes to the following files would be overwritten by merge:
       file.txt
Please, commit your changes or stash them before you can merge.
Aborting

Postępuj zgodnie z tym procesem:

git status  # local changes to `file`
git stash list  # further changes to `file` we want to merge
git commit -m "WIP" file
git stash pop
git commit -m "WIP2" file
git rebase -i HEAD^^  # I always use interactive rebase -- I'm sure you could do this in a single command with the simplicity of this process -- basically squash HEAD into HEAD^
# mark the second commit to squash into the first using your EDITOR
git reset HEAD^

I pozostaniesz z całkowicie scalonymi lokalnymi zmianami file, gotowymi do dalszej pracy / czyszczenia lub dokonania pojedynczego dobrego zatwierdzenia. Lub, jeśli znasz scalone zawartość filebędzie prawidłowa, można napisać wiadomość montażu i pominąć git reset HEAD^.


0

Być może nie jest to najgorszy pomysł, aby połączyć (poprzez difftool) z ... tak ... oddziału!

> current_branch=$(git status | head -n1 | cut -d' ' -f3)
> stash_branch="$current_branch-stash-$(date +%yy%mm%dd-%Hh%M)"
> git stash branch $stash_branch
> git checkout $current_branch
> git difftool $stash_branch

0

możesz łatwo

  1. Zatwierdź bieżące zmiany
  2. Uwolnij swój zapas i rozwiąż konflikty
  3. Zatwierdź zmiany w skrytce
  4. Miękki reset do zatwierdzenia, z którego pochodzisz (ostatnie prawidłowe zatwierdzenie)

-1

Inną opcją jest wykonanie kolejnego „git stash” lokalnych niezatwierdzonych zmian, a następnie połączenie dwóch skrytek git. Niestety git wydaje się nie mieć sposobu na łatwe połączenie dwóch skrytek. Tak więc jedną z opcji jest utworzenie dwóch plików .diff i zastosowanie ich obu - w każdym razie nie jest to dodatkowe zatwierdzenie i nie wymaga dziesięcioetapowego procesu: |

jak: https://stackoverflow.com/a/9658688/32453


Sprawia, że ​​problem stosowania jednej różnicy staje się problemem stosowania dwóch różnic. Ponadto zaakceptowane rozwiązanie nie wymaga zatwierdzenia, a jedynie etap i jest to tylko jedno polecenie (git add). (Nie jestem zwycięzcą).
Eike

Dla mnie przynajmniej wydaje się to prostsze, mniej magii voodoo ... na zdrowie!
rogerdpack,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.