Odkąd git cherry-pick
nauczyliśmy się stosować wiele zatwierdzeń, to rozróżnienie rzeczywiście stało się nieco dyskusyjne, ale jest to coś, co można nazwać ewolucją zbieżną ;-)
Prawdziwa różnica polega na pierwotnym zamiarze stworzenia obu narzędzi:
git rebase
Zadaniem jest przekierowanie serii zmian, które programista ma w swoim prywatnym repozytorium, utworzonych dla wersji X jakiejś gałęzi nadrzędnej, do wersji Y tej samej gałęzi (Y> X). To skutecznie zmienia podstawę tej serii zatwierdzeń, stąd „ponowne podstawy”.
(Pozwala również programistom na przeszczepienie serii zatwierdzeń do dowolnego arbitralnego zatwierdzenia, ale ma to mniej oczywiste zastosowanie).
git cherry-pick
służy przeniesieniu interesującego zatwierdzenia z jednej linii rozwoju do drugiej. Klasycznym przykładem jest przeniesienie poprawki bezpieczeństwa dokonanej na niestabilnej gałęzi programistycznej do gałęzi stabilnej (konserwacyjnej), gdzie merge
nie ma sensu, ponieważ przyniosłaby całą masę niechcianych zmian.
Od pierwszego pojawienia się, git cherry-pick
był w stanie wybrać kilka zatwierdzeń naraz, jeden po drugim.
Dlatego prawdopodobnie najbardziej uderzającą różnicą między tymi dwoma poleceniami jest sposób, w jaki traktują gałąź, na której pracują: git cherry-pick
zwykle przenosi zatwierdzenie z innego miejsca i stosuje je na bieżącej gałęzi, nagrywając nowe zatwierdzenie, podczas gdy git rebase
bierze bieżącą gałąź i przepisuje seria własnych wskazówek zatwierdza się w taki czy inny sposób. Tak, jest to mocno głupi opis tego, co git rebase
można zrobić, ale jest celowe, aby spróbować zagłębić się w ogólny pomysł.
Zaktualizuj, aby dokładniej wyjaśnić przykład git rebase
omawianego użycia .
W tej sytuacji
Księga stwierdza:
Jest jednak inny sposób: możesz wziąć poprawkę zmiany, która została wprowadzona w C3 i ponownie zastosować ją na C4. W Git nazywa się to rebasingiem. Za pomocą polecenia rebase możesz wziąć wszystkie zmiany, które zostały zatwierdzone w jednej gałęzi i zastosować je w innej.
W tym przykładzie uruchomisz następujące polecenie:
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
W tym przykładzie „haczyk” polega na tym, że w tym przykładzie gałąź „eksperymentu” (temat do zmiany bazy) została pierwotnie oddzielona od gałęzi „nadrzędnej”, a zatem dzieli z nią zatwierdzenia od C0 do C2 - w rzeczywistości „eksperyment” to master ”aż do C2 włącznie, plus zatwierdzenie C3. (To najprostszy możliwy przypadek; oczywiście „eksperyment” może zawierać kilkadziesiąt zatwierdzeń na podstawie oryginalnej bazy).
Teraz git rebase
mówi się, aby zmienić bazę „eksperymentu” na aktualną końcówkę „mistrza” i git rebase
wygląda tak:
- Uruchamia,
git merge-base
aby zobaczyć, jakie jest ostatnie zatwierdzenie wspólne zarówno dla „eksperymentu”, jak i dla „mistrza” (innymi słowy, jaki jest cel przekierowania). To jest C2.
- Oszczędza wszystkie zatwierdzenia dokonane od momentu przekierowania; w naszym przykładzie z zabawką jest to po prostu C3.
- Przewija HEAD (co wskazuje na końcówkę zatwierdzenia „eksperymentu” przed rozpoczęciem operacji), aby wskazać końcówkę „master” - ponownie bazujemy na niej.
- Próbuje zastosować po kolei każdy z zapisanych zatwierdzeń (jak gdyby
git apply
). W naszym przykładzie z zabawką to tylko jedno zatwierdzenie, C3. Powiedzmy, że jego aplikacja wygeneruje zatwierdzenie C3 '.
- Jeśli wszystko poszło dobrze, odniesienie do „eksperymentu” jest aktualizowane tak, aby wskazywało na zatwierdzenie wynikające z zastosowania ostatniego zapisanego zatwierdzenia (w naszym przypadku C3 ').
Wróćmy teraz do twojego pytania. Jak widać, technicznie rzecz biorąc, git rebase
przeszczepia tutaj serię zatwierdzeń od „eksperymentu” do końcówki „mistrza”, więc można słusznie stwierdzić, że w tym procesie rzeczywiście istnieje „inna gałąź”. Ale sedno jest takie, że zatwierdzenie wskazówki z „eksperymentu” okazało się nowym zatwierdzeniem wskazówki w „eksperymencie”, po prostu zmieniło swoją podstawę:
Ponownie, technicznie można powiedzieć, że git rebase
tutaj włączono pewne zatwierdzenia z „mastera” i jest to absolutnie poprawne.
Dzięki cherry-pick oryginalne zatwierdzenia / rozgałęzienia pozostają w pobliżu i tworzone są nowe zatwierdzenia. W przypadku rebase cała gałąź jest przenoszona z gałęzią wskazującą na powtórzone zatwierdzenia.
Powiedzmy, że zacząłeś od:
Rebase:
Dostajesz:
Zbiór wiśni:
Dostajesz:
aby uzyskać więcej informacji o git, ta książka zawiera większość tego (http://git-scm.com/book)
źródło
topic
rebased na wierzchumaster
, nie zawiera pominiętych zatwierdzeń, więc do której gałęzi będą one należeć?git checkout topic
a potemgit reset --hard C'
po zerwaniu wiśni, masz taki sam wynik, jak po ponownym bazowaniu. Uratowałem się przed wieloma konfliktami dotyczącymi scalania, używając wyboru wiśni zamiast ponownego bazowania, ponieważ wspólny przodek był dawno temu.git
-guru, ale torebase
/cherry-pick
jest jeden ze wszystkich szczegółów, zgit
którymi miałem problem ze zrozumieniem.git checkout -b
, z którą nie ma nic wspólnegogit cherry-pick
. Lepszym sposobem na wyjaśnienie tego, co próbujesz powiedzieć, byłoby: „biegnieszgit rebase
potopic
gałęzi i mijasz jąmaster
; biegaszgit cherry-pick
namaster
gałęzi i przekazujesz ją (zatwierdza)topic
. ”Zbieranie wiśni działa dla indywidualnych zatwierdzeń .
Kiedy dokonujesz zmiany bazy, wszystkie zmiany w historii zostaną zastosowane do HEAD gałęzi, których tam brakuje.
źródło
git cherry-pick foo~3..foo
i pobrać zmiany z wierzchołka drzewa z "foo" wybieranego jeden po drugim.git am
na nim. Podczas gdy najlepszy wybór stosuje zatwierdzanie po zatwierdzeniu (prawdopodobnie tworząc skrzynkę pocztową z pojedynczą wiadomością dla każdej łatki). Moja rebase nie powiodła się, ponieważ plik skrzynki pocztowej, który tworzył, zabrakło miejsca na dysku, ale najlepszy wybór z tym samym zakresem wersji powiódł się (i wydaje się działać szybciej).Krótka odpowiedź:
Odpowiedzi podane powyżej są dobre, chciałem tylko podać przykład, próbując zademonstrować ich wzajemne powiązania.
Nie zaleca się zastępowania „git rebase” tą sekwencją działań, jest to po prostu „dowód słuszności koncepcji”, który, mam nadzieję, pomaga zrozumieć, jak to działa.
Biorąc pod uwagę następujące repozytorium zabawek:
Powiedzmy, że mamy kilka bardzo ważnych zmian (zatwierdzenia od # 2 do # 5) w pliku master, które chcemy uwzględnić w naszej gałęzi test_branch_1. Zwykle po prostu przełączamy się na gałąź i robimy „git rebase master”. Ale ponieważ udajemy, że jesteśmy wyposażeni tylko w „git cherry-pick”, robimy:
Po tych wszystkich operacjach nasz wykres zatwierdzenia będzie wyglądał następująco:
Jak widać, zatwierdzenia # 6 i # 7 zostały zastosowane przeciwko 7254931 (zatwierdzenie napiwku mastera). HEAD został przeniesiony i wskazuje zatwierdzenie, które jest w istocie końcówką nowej gałęzi. Teraz wszystko, co musimy zrobić, to usunąć stary wskaźnik gałęzi i utworzyć nowy:
test_branch_1 jest teraz zakorzeniony z ostatniej pozycji głównej. Gotowe!
źródło
cherry-pick
jest w stanie zastosować szereg zatwierdzeń, myślę, że tak. Chociaż jest to trochę dziwny sposób robienia rzeczy, nic nie stoi na przeszkodzie, abymaster
wybrać wszystkie zatwierdzenia w gałęzi feature , a następnie usunąć gałąź feature i ponownie utworzyć ją tak, aby wskazywała na koniecmaster
. Można myślećgit rebase
jak o sekwencjigit cherry-pick feature_branch
,git branch -d feature_branch
igit branch feature_branch master
.Oba są poleceniami do przepisywania zatwierdzeń jednej gałęzi na drugiej: różnica polega na tym, która gałąź - „twoja” (aktualnie wyewidencjonowana
HEAD
) lub „ich” (gałąź przekazana jako argument do polecenia) jest podstawa do tego przepisać.git rebase
przyjmuje początkowe zatwierdzenie i odtwarza twoje zatwierdzenia jako następujące po ich (początkowym zatwierdzeniu).git cherry-pick
przyjmuje zestaw zatwierdzeń i odtwarza ich zatwierdzenia jako nadchodzące po twoim (twoimHEAD
).Innymi słowy, te dwa polecenia są, w swojej podstawowej zachowania (ignorując ich rozbieżne charakterystyk, nazywając konwencje i opcje poprawy), symetryczne : sprawdzeniu oddział
bar
i działagit rebase foo
ustawia siębar
gałąź do tej samej historii jak sprawdzanie oddziałfoo
i działagit cherry-pick ..bar
nie stawiałfoo
do (zmiany zfoo
, a następnie zmiany zbar
).Jeśli chodzi o nazwy, różnicę między tymi dwoma poleceniami można zapamiętać, ponieważ każde z nich opisuje, co robi z bieżącą gałęzią:
rebase
sprawia, że druga kieruje nową bazą zmian, podczas gdycherry-pick
wybiera zmiany z drugiej gałęzi i umieszcza je na wierzchu TwójHEAD
(jak wiśnie na lodzie).źródło
Obie robią bardzo podobne rzeczy; główna różnica koncepcyjna polega na (w uproszczeniu), że:
rebase przenosi zatwierdzenia z bieżącej gałęzi do innej .
wybrane kopie zatwierdzeń z innej gałęzi do bieżącej gałęzi .
Korzystanie z diagramów podobnych do odpowiedzi @Kenny Ho :
Biorąc pod uwagę ten stan początkowy:
... i zakładając, że chcesz uzyskać zmiany z
topic
gałęzi odtwarzane na wierzchu bieżącejmaster
gałęzi, masz dwie możliwości:Korzystanie z rebase: najpierw udałoby się
topic
zrobićgit checkout topic
, a następnie przenieść gałąź, uruchamiającgit rebase master
, produkując:Wynik: Twoja obecna gałąź
topic
została przeniesiona (przeniesiona) namaster
. Gałąź została zaktualizowana, podczas gdy oddział pozostał na swoim miejscu.topic
master
Używając `` cherry-pick '' : najpierw przejdź
master
przez wykonaniegit checkout master
, a następnie skopiuj gałąź, uruchamiającgit cherry-pick topic~3..topic
(lub, równoważnie,git cherry-pick B..G
), wytwarzając:Wynik: zatwierdzenia z
topic
zostały skopiowane domaster
. Gałąź została zaktualizowana, podczas gdy oddział pozostał na swoim miejscu.master
topic
Oczywiście tutaj trzeba było wyraźnie powiedzieć cherry-pick, aby wybrał sekwencję zatwierdzeń , używając notacji zakresu
foo..bar
. Gdybyś po prostu przekazał nazwę gałęzi, tak jak wgit cherry-pick topic
, odebrałby on tylko zmianę na końcu gałęzi, co dałoby:źródło