Jak skopiować zatwierdzenia z jednego oddziału do drugiego?

727

Mam dwa oddziały od mojego mistrza:

  • v2.1 : (wersja 2) Pracuję od kilku miesięcy
  • wss : że stworzyłem wczoraj, aby dodać jedną konkretną funkcję do mojego mistrza (w produkcji)

Czy istnieje sposób na skopiowanie wczorajszych zatwierdzeń z wss do wersji 2.1?

Bob Walsh
źródło
Aby po prostu skopiować zatwierdzenia (lub zakres zatwierdzeń) z jednego oddziału do drugiego, ta odpowiedź pomogła mi najlepiej: stackoverflow.com/questions/1994463/…
caramba
Konkretne
wybieranie

Odpowiedzi:

563

Naprawdę powinieneś mieć przepływ pracy, który pozwoli ci to wszystko scalić:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (wss)

Więc wszystko co musisz zrobić, to git checkout v2.1i git merge wss. Jeśli z jakiegoś powodu tak naprawdę nie możesz tego zrobić i nie możesz użyć git rebase, aby przenieść gałąź wss we właściwe miejsce, polecenie pobrania jednego skoku z dowolnego miejsca i zastosowania go w innym miejscu jest git cherry-pick . Po prostu sprawdź gałąź, na której chcesz ją zastosować, i uruchom git cherry-pick <SHA of commit to cherry-pick>.

Niektóre sposoby rebase mogą cię uratować:

Jeśli twoja historia wygląda tak:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (v2-only) - x - x - x (wss)

Możesz użyć git rebase --onto v2 v2-only wssdo przeniesienia wss bezpośrednio na v2:

- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - x - x (v2-only)
           \
             x - x - x (wss)

Następnie możesz się połączyć! Jeśli naprawdę, naprawdę, naprawdę nie możesz dojść do punktu, w którym możesz się połączyć, nadal możesz użyć rebase, aby skutecznie wykonać kilka wyborów jednocześnie:

# wss-starting-point is the SHA1/branch immediately before the first commit to rebase
git branch wss-to-rebase wss
git rebase --onto v2.1 wss-starting-point wss-to-rebase
git checkout v2.1
git merge wss-to-rebase

Uwaga: powodem jest to, że wymaga to dodatkowej pracy, ponieważ tworzy duplikaty zatwierdzeń w repozytorium. To naprawdę nie jest dobra rzecz - celem łatwego rozgałęziania i łączenia jest możliwość zrobienia wszystkiego, czyniąc zatwierdzenie (-a) w jednym miejscu i łącząc je tam, gdzie są potrzebne. Duplikaty zatwierdzeń oznaczają zamiar, aby nigdy nie łączyć tych dwóch gałęzi (jeśli zdecydujesz, że chcesz później, dostaniesz konflikty).

Cascabel
źródło
1
Nie można zgodzić się więcej z tą odpowiedzią. +1. Zobacz też moją starą odpowiedź, która ilustruje konsekwencje zbierania wiśni: stackoverflow.com/questions/881092/...
VonC
18
Znakomita odpowiedź, jak to zrobić we właściwy sposób! Chciałbym też dwukrotnie głosować za wysiłkiem tworzenia diagramów ASCII.
gotgenes
@VonC: Dziękuję za wsparcie i dodatkowe informacje na temat tego, dlaczego nie wybrać Cherry - wiem, że trochę tam przeszedłem. @gotgenes: Dzięki! Myślę, że jest to całkowicie warte wysiłku - wystarczy spojrzeć na stronę git-rebase. Nie ma lepszego sposobu na wyjaśnienie tego.
Cascabel
Co do tego, dlaczego możesz nie być w stanie scalić - scalanie Git nie działa dobrze z git-svn. Aby skopiować serię zatwierdzeń z jednej gałęzi SVN do drugiej, ostatecznie wybrałem je, a następnie wykonałem interaktywny rebase / reword, aby usunąć nieprawidłowe git-svn-idodwołania przed dcommitponownym włożeniem. Chociaż prawdopodobnie mogłem pominąć krok po kroku i po prostu sam użyć bazy.
Bob
1
Oto mój przykład użycia: krytyczne poprawki błędów zostały wprowadzone do gałęzi funkcji. Potrzebuję go w trybie mistrza, aby móc teraz rozpocząć produkcję. To uratuje mój tyłek.
Kapitan Hypertext
910

Posługiwać się

git cherry-pick <commit>

złożyć wniosek <commit>w bieżącym oddziale .

Prawdopodobnie osobiście sprawdziłbym zatwierdzenia, które wybrałem, gitki wybrałbym je kliknięciem prawym przyciskiem myszy na miejscu zatwierdzenia.


Jeśli chcesz iść bardziej automatycznie (ze wszystkimi niebezpieczeństwami) i zakładając, że wszystkie zatwierdzenia od wczoraj wydarzyły się na wss, możesz wygenerować listę zatwierdzeń za pomocą git log(z --prettysugestią Jefromi)

git log --reverse --since=yesterday --pretty=%H

więc wszystko razem przy założeniu, że używasz bash

for commit in $(git log --reverse --since=yesterday --pretty=%H);
do
    git cherry-pick $commit
done

Jeśli coś pójdzie nie tak (istnieje duży potencjał), masz kłopoty, ponieważ działa to przy kasie na żywo, więc albo wybierz ręczne wybieranie wiśni, albo skorzystaj z rebase, jak sugeruje Jefromi.

Benjamin Bannier
źródło
Wszystkie symbole zastępcze dla opcji --pretty znajdują się na stronie podręcznika git-log. Możesz uzyskać dowolny format - szczególnie przydatny do uzyskania potrzebnych pól skryptu w łatwej do analizy formie.
Cascabel,
Chciałbym również zauważyć, że zakładając, że naprawdę chcesz tworzyć duplikaty zatwierdzeń, metoda zastosowana git rebasew mojej odpowiedzi jest bardziej niezawodna. W szczególności, używając takiej pętli for, jeśli jeden z typów wybierania nie powiedzie się, nadal będzie próbował wykonać resztę. To jest ... bardzo, bardzo źle, powiedzmy.
Cascabel
2
Zgoda. Dlatego nigdy go nie używam, ale robię to ręcznie. Ale wybór „wiśni” jest nadal odpowiedzią, przynajmniej na tytuł pytania. Zmodyfikowałem odpowiedź.
Benjamin Bannier
1
Ktoś zaangażował się w starą / niepoprawną gałąź, a cherry-pick pozwala mi umieścić to zatwierdzenie w odpowiedniej gałęzi (zachowując je jako podmiot zatwierdzający). Doskonały.
Patrick,
8
Rzadki widok, gitodpowiedź, która jest prosta i prosta do rozwiązania, zamiast wędrować przez zawiłości gita, aby udowodnić, jak dobrze odpowiada na to osoba odpowiadająca.
Przemek D
74

git cherry-pick : Zastosuj zmiany wprowadzone przez niektóre istniejące zatwierdzenia

Załóżmy, że mamy gałąź A z zatwierdzeniami (X, Y, Z). Musimy dodać te zobowiązuje się do oddziału B . Użyjemy cherry-pickoperacji.

Gdy używamy cherry-pick, powinniśmy dodać zobowiązuje na oddział B w tej samej kolejności chronologicznej, że rewizje pojawiają się w Oddziale A .

cherry-pick obsługuje szereg zatwierdzeń, ale jeśli masz scalenia zatwierdzeń w tym zakresie, staje się to naprawdę skomplikowane

git checkout B
git cherry-pick SHA-COMMIT-X
git cherry-pick SHA-COMMIT-Y
git cherry-pick SHA-COMMIT-Z

Przykład przepływu pracy:

wprowadź opis zdjęcia tutaj

Możemy używać cherry-pickz opcjami

-e lub --edit : Dzięki tej opcji, git cherry-pick pozwoli ci edytować komunikat zatwierdzenia przed zatwierdzeniem.

-n lub --no-commit : zwykle polecenie automatycznie tworzy sekwencję zatwierdzeń. Ta flaga stosuje zmiany niezbędne do wybrania każdego nazwanego zatwierdzenia do drzewa roboczego i indeksu, bez dokonywania żadnych zatwierdzeń. Ponadto, gdy używana jest ta opcja, indeks nie musi być zgodny z zatwierdzeniem HEAD. Wybierania „wiśniowego” dokonuje się względem początkowego stanu indeksu.

Oto ciekawy artykuł dotyczący cherry-pick.

Lyes CHIOUKH
źródło
19

Możesz utworzyć łatkę z zatwierdzeń, które chcesz skopiować i zastosować łatkę do gałęzi docelowej.

Charles Ma
źródło
16
Nawet jeśli z jakiegoś powodu naprawdę chcesz użyć łatek (e) zamiast cherry-pick (s) / rebase, najprostszym sposobem na to jest użycie git format-patch <revision range>i git am *.patch.
Cascabel
Wymaga checkoutinnej gałęzi.
CoolMind,
12

Lub jeśli jesteś trochę mniej po stronie ewangelisty, możesz zrobić trochę brzydki sposób, którego używam. W deploy_template są zatwierdzenia, które chcę skopiować na moim systemie głównym jako wdrożenie w oddziale

git branch deploy deploy_template
git checkout deploy
git rebase master

Spowoduje to utworzenie nowego wdrożenia gałęzi (używam opcji -f, aby zastąpić istniejący gałąź wdrażania) na parametrze deploy_template, a następnie przestawienie tej nowej gałęzi na master, pozostawiając niezmieniony szablon wdrażania.

Petr Sykora
źródło
1

W prostym przypadku po prostu skopiowania ostatniego zatwierdzenia z gałęzi wss do wersji 2.1, możesz po prostu pobrać identyfikator id ( git log --oneline | head -n 1) i wykonać:

git checkout v2.1
git merge <commit>
zeroimpl
źródło
Wymaga to wyewidencjonowania w innym oddziale.
CoolMind
1

Polecenie cherry-pick może odczytać listę zatwierdzeń ze standardowego wejścia.

Następujące polecenie cherry-picks zatwierdza autor Jan, które istnieją w gałęzi „rozwijania”, ale nie w gałęzi „wydania”, i robi to w kolejności chronologicznej.

git log develop --not release --format=%H --reverse --author John | git cherry-pick --stdin
Gebb
źródło