Jak scalić moje lokalne niezatwierdzone zmiany z innym oddziałem Git?


621

Jak mogę wykonać następujące czynności w Git?

Mój obecny oddział to oddział 1 i wprowadziłem kilka lokalnych zmian. Teraz jednak zdaję sobie sprawę, że tak naprawdę zamierzałem zastosować te zmiany w gałęzi 2. Czy istnieje sposób na zastosowanie / scalenie tych zmian, aby stały się lokalnymi zmianami w oddziale 2 bez popełniania ich w oddziale 1?


2
Tutaj na SO jest świetny samouczek Git . Jest to rodzaj centrum dla wszystkich pytań git dotyczących przepełnienia stosu.
Decio Lira,

Odpowiedzi:


896

Ponieważ Twoje pliki nie są jeszcze zatwierdzone w branch1:

git stash
git checkout branch2
git stash pop

lub

git stash
git checkout branch2
git stash list       # to check the various stash made in different branch
git stash apply x    # to select the right one

Jak skomentował przez benjohn (zobacz git stashstronę man ):

Aby ukryć również aktualnie nieśledzone (nowo dodane) pliki, dodaj argument -u:

git stash -u

2
Zapraszamy. Inne przykłady stash stosowania przy unethicalblogger.com/posts/2008/11/... .
VonC

2
Jeśli szukasz rozwiązania tego samego problemu, ale z TFS, równoważnym rozwiązaniem jest odłożenie zmian na później, a następnie skorzystanie z Narzędzi TFS Power Tools, aby przejść do właściwej gałęzi za pomocą przełącznika / migrate.
xr280xr

1
To zadziałało dla mnie. Musiałem jednak również utworzyć lokalny oddział, aby działał „stash pop”. Zapoznaj się z stackoverflow.com/questions/1783405/git-checkout-remote-branch, jeśli dzieje się coś podobnego.
mimoralea

21
Również schować obecnie nieśledzone (nowo dodane pliki) , dodać argument -u, tak: git stash -u.
Benjohn

2
@Benjohn Dobra uwaga. W odpowiedzi umieściłem twój komentarz dla większej widoczności.
VonC

84

Ukrywanie, tymczasowe zatwierdzenia i zmiany zasad mogą być przesadą. Jeśli jeszcze nie dodałeś zmienionych plików do indeksu, być może będziesz mógł po prostu pobrać drugą gałąź.

git checkout branch2

Działa to tak długo, jak długo edytowane pliki nie różnią się między oddziałem 1 i oddziałem 2. Zostawi cię na gałęzi 2 z zachowanymi zmianami roboczymi. Jeśli są różne, możesz określić, że chcesz scalić lokalne zmiany ze zmianami wprowadzonymi przez zmianę gałęzi z -mopcją kasy.

git checkout -m branch2

Jeśli dodałeś zmiany do indeksu, najpierw cofnij je, resetując. (Pozwoli to zachować kopię roboczą, po prostu usuniesz zmiany etapowe).

git reset

3
Pomyślałem, że skrytka jest „prostsza” w jakiś sposób do zrozumienia, ale twoje podejście jest lepsze biorąc pod uwagę katalog roboczy w różnych gałęziach. +1
VonC

6
Zwykła tradycyjna kasa wydawała się bardziej odpowiednia do danego problemu. kasa jest lżejsza, po prostu aktualizuje pliki, które należy zmienić. Być może łatwiej jest zrozumieć podejście ukryte, lub może po prostu nie być oczywiste, że kasa jest „bezpieczna” w tym przypadku użycia.
CB Bailey,

Jeśli checkout -mskrytka nie jest w niektórych sytuacjach „bezpieczna” (być może spowodowałaby konflikt scalania), czy skrytka miałaby jakąś przewagę (np. Czy możesz odpakować skrytkę)?
Craig McQueen

1
@craigMcQueen Nie możesz odpakować wyskakującej skrytki, ale skrytka narzeka na konflikty, kiedy ją wyskoczysz. Możesz naprawić konflikty, a następnie zatwierdzić, ale w tym przypadku oryginalna skrytka wciąż znajduje się na stosie! :)
Shaun F

W przypadku konfliktu scalenia nie tworzy się kopii zapasowej plików jako .orig?
żartuje

13

Krótszą alternatywą dla wcześniej wspomnianego podejścia do ukrywania byłoby:

Tymczasowo przenieś zmiany do skrytki.

  1. git stash

Utwórz nową gałąź i przejdź do niej, a następnie włóż do niej skrytkę w zaledwie jednym kroku.

  1. git stash branch new_branch_name

Potem tylko addi commitzmiany w tym nowym oddziale.


10

OSTRZEŻENIE: Nie dla początkujących użytkowników.

To pojawia się na tyle w moim przepływie pracy, że prawie próbowałem napisać dla niego nowe polecenie git. Zwykły git stashprzepływ jest drogą, ale jest trochę niezręczny. Zwykle najpierw dokonuję nowego zatwierdzenia, ponieważ jeśli patrzyłem na zmiany, wszystkie informacje są w mojej głowie świeże i lepiej po prostu zacząć od git committego, co znalazłem (zwykle poprawkę należącą do mistrza, którą odkryłem podczas pracy nad gałąź funkcji) od razu.

Pomocne jest również - jeśli często zdarza się takie sytuacje - mieć obok katalogu bieżącego inny katalog roboczy, w którym zawsze znajduje się mastergałąź.

Jak to osiągam, wygląda to tak:

  1. git commit zmiany od razu z dobrym komunikatem zatwierdzenia.
  2. git reset HEAD~1 aby cofnąć zatwierdzenie z bieżącego oddziału.
  3. (opcjonalnie) kontynuuj pracę nad tą funkcją.

Czasami później (asynchronicznie) lub natychmiast w innym oknie terminala:

  1. cd my-project-master który jest innym WDem, który udostępnia to samo .git
  2. git reflog znaleźć poprawkę, którą właśnie stworzyłem.
  3. git cherry-pick SHA1 zatwierdzenia.

Opcjonalnie (nadal asynchronicznie) możesz następnie zmienić bazę (lub scalić) gałąź funkcji, aby uzyskać poprawkę, zwykle gdy masz zamiar przesłać PR i wyczyściłeś już gałąź funkcji i WD:

  1. cd my-project który jest głównym WD, nad którym pracuję.
  2. git rebase master aby uzyskać poprawki błędów.

W ten sposób mogę nieprzerwanie pracować nad tą funkcją i nie muszę się martwić o git stashcokolwiek, czy muszę wyczyścić WD przed git checkout(a następnie ponownie sprawdzić wycofanie gałęzi funkcji) i nadal mieć wszystkie moje poprawki masterzamiast ukryty w mojej gałęzi funkcji.

IMO git stashi git checkoutjest prawdziwą PIA, gdy jesteś w trakcie pracy nad jakąś dużą funkcją.


Ciekawa i ważna alternatywa dla mojej odpowiedzi. +1
VonC

Pochodzisz z rtęci? my-project-masterDzieląc te same .gitbrzmi to podoba. Dlaczego nie git checkout -b bugfixABC; git commit -a; git reset HEAD^ --hard, a później (asynchronicznie) podczas master, git cherry-pick <SHA1 of the commit(s) in bugfixABC? (lub nawet, aby uniknąć konieczności szukania SHA1, git rebase --onto master feature bugfixABCz dowolnego miejsca, w którym aktualnie się znajdujesz. Co oznacza, że ​​możesz to zrobić bezpośrednio po git resetpowyższym, gdy jesteś włączony feature).
Gauthier

Jednak OP brzmi, jakby nie byli gotowi do wprowadzenia zmian, w takim przypadku checkout -mjest po prostu lepiej.
Gauthier

2

Jeśli chodzi o zatwierdzone zmiany, powinieneś rzucić okiem na git-rebase, ale jak wskazano w komentarzu VonC, gdy mówisz o lokalnych zmianach, git-stash z pewnością byłby dobrym sposobem na zrobienie tego.


Nie rozumiem tego rozwiązania: przepisałoby historię zatwierdzania oddziału 2 z oddziału 1 ... po co uzyskiwać wszystkie zatwierdzone zmiany z oddziału 1 w oddziale 2, gdy chcemy tylko uzyskać lokalne niezaangażowane zmiany oddziału 1 w oddziale 2? ...
VonC

@VonC: zgodził się, w tym przypadku rebase pobiera wszystkie zatwierdzone zmiany od ostatniego połączenia między oddziałami w oddział1. Na początku nie otrzymałem parametru „niezaangażowanego” tego pytania. rebase nie jest dobrą odpowiedzią.
claf

@claferri: pfew ... Zaczyna mnie boleć głowa;) Poparłbym twoją odpowiedź, ale skoro sam ją opublikowałem, nastąpił „wyraźny konflikt interesów”. W przypadku Twojego zaktualizowanego postu wcale nie muszę teraz głosować negatywnie. Dzięki :)
VonC

@VonC: następnym razem nie krępuj się głosować, dopóki moja odpowiedź jest tak samo zła jak ta;)
claf

1

Dotychczasowe odpowiedzi nie są idealne, ponieważ wymagają dużo niepotrzebnej pracy w celu rozwiązania konfliktów scalania lub przyjmują zbyt wiele założeń, które często są fałszywe. Oto jak to zrobić idealnie. Link jest do mojej własnej strony.

Jak zatwierdzić w innym oddziale w git

Masz niezatwierdzone zmiany my_branch, do których chcesz się zobowiązać master, bez zatwierdzania wszystkich zmian od my_branch.

Przykład

git merge master
git stash -u
git checkout master
git stash apply
git reset
git add example.js
git commit
git checkout .
git clean -f -d
git checkout my_branch
git merge master
git stash pop

Wyjaśnienie

Zacznij od połączenia mastersię ze swoim oddziałem, ponieważ i tak będziesz musiał to zrobić ostatecznie, a teraz jest najlepszy czas na rozwiązanie wszelkich konfliktów.

-uOpcja (aka --include-untracked) w git stash -uzapobiega zgubieniu plików nieśledzone kiedy później zrobić git clean -f -dwewnątrz master.

Po git checkout mastertym ważne jest, aby tego NIE robić git stash pop, ponieważ będziesz potrzebować tej skrytki później. Jeśli włączysz utworzoną skrytkę, my_brancha następnie git stashw nią masterwejdziesz, spowodujesz niepotrzebne konflikty scalania, gdy później zastosujesz tę skrytkę my_branch.

git resetodsłania wszystko, co wynika z git stash apply. Na przykład pliki, które zostały zmodyfikowane w skrytce, ale nie istnieją, mastersą przenoszone jako konflikty „usunięte przez nas”.

git checkout .i git clean -f -dodrzucić wszystko, co nie zostało popełnione: wszystkie zmiany w śledzonych plikach oraz wszystkie nieśledzone pliki i katalogi. Są już zapisane w skrytce, a pozostawienie masterich spowoduje niepotrzebne konflikty scalania przy ponownym włączeniu my_branch.

Ostatni git stash popbędzie oparty na oryginale my_branch, a więc nie spowoduje konfliktów scalania. Jeśli jednak twoja skrytka zawiera nieśledzone pliki, które zobowiązałeś się opanować, git będzie narzekać, że „nie można przywrócić nieśledzonych plików ze skrytki”. Aby rozwiązać ten konflikt, należy usunąć te pliki z drzewa pracy, potem git stash pop, git add .i git reset.


2
Twoja odpowiedź nie została usunięta, ponieważ była połączona z Twoją witryną, została usunięta, ponieważ była identyczna z inną odpowiedzią z innego konta. Widzę, że drugie konto ma taki sam profil jak twoje, czy używasz dwóch kont? Możesz połączyć oba konta. Również oflaguj mod, aby wyjaśnić sytuację, a możesz uzyskać oryginalną odpowiedź (z upvote) usuniętą.

1
Nie można przechowywać je oddzielnie, jeśli są one połączone, ale może mieć wiele kont, tak długo, jak nie używać ich do popełniania oszustw głosowania (lub mają je współdziałają ze sobą na ogół). Wyjaśnij swoją sytuację modowi. Ponadto usunięcie było szczerym błędem. Jak możesz oczekiwać, że ktoś powie, że korzystasz z dwóch różnych kont?

3
Musisz oflagować swój post i użyć opcji Inne, aby zwrócić uwagę modów, na które nie zwracają uwagi podczas edycji usuniętej odpowiedzi. Już oznaczyłem twoje posty, aby zwrócić uwagę na mod, ale są dość zajęte, więc bądź cierpliwy, w końcu się z tobą skontaktują.

1
Nie publikuj zduplikowanych treści, szczególnie z różnych kont. Głosuj lub oznacz, aby zamknąć jako duplikat, jeśli dwa pytania są takie same.
Bill the Lizard
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.