TL;DR: git cherry-pick <sha> kopiuje jeden commit z dowolnej gałęzi na twoją obecną — ten sam patch, nowy SHA, żadna historia nie ruszona. Dla kilku commitów wypisz SHA-y albo użyj zakresu (git cherry-pick A..B); pamiętaj, że zakres pomija A, więc napisz A^..B, żeby go włączyć. Jeśli cherry-pick zatrzyma się na konflikcie: rozwiąż, git add, potem git cherry-pick --continue. Cherry-pick służy do przenoszenia konkretnego fixa — gdy chcesz wszystko z drugiej gałęzi, użyj merge albo rebase.
Co tak naprawdę robi git cherry-pick?
Cherry-pick bierze istniejący commit i aplikuje jego diff jako nowy commit na twojej obecnej gałęzi. Oryginał zostaje tam, gdzie był; kopia dostaje świeży SHA. Git niczego nie „przenosi” — ludzie, którzy później dziwią się, czemu commit dalej widać na starej gałęzi, patrzą dokładnie na to.
Model kopiuj-zamiast-przenoś rozstrzyga, kiedy cherry-pick to właściwe narzędzie:
- Potrzebujesz jednego fixa z gałęzi feature na
mainjuż teraz, bez mergowania reszty. - Hotfix skomitowany na złej gałęzi ma wylądować na dobrej.
- Patch trzeba odtworzyć na gałęzi release, która nigdy nie merdżuje z
main.
Komplementarną umiejętnością jest wycofywanie commita, który okazał się błędem — mechanika tego jest opisana w git undo last commit: jak zachować zmiany.
Jak cherry-picknąć commit z innej gałęzi?
Znajdź SHA, przeskocz na docelową gałąź, pickuj:
# 1. Znajdź commit na gałęzi źródłowej
git log feature/payment-fix --oneline -5
# 2. Przełącz się na gałąź, która ma go otrzymać
git switch main
# 3. Skopiuj go
git cherry-pick 1a2b3c4 Dwie wygody warte znajomości:
git cherry-pick <branch>pickuje wierzchołek tej gałęzi — wygodne, ale łatwe do zrobienia przez przypadek, gdy twoje wyobrażenie o „wierzchołku” jest nieaktualne.- Po picku
git log -1 --statpotwierdza, co wylądowało. Sekunda czytania, a oszczędza revert.
Commity zostają na feature/payment-fix; skasuj tę gałąź, kiedy chcesz — skopiowany commit na main ma własny SHA i nie zależy od starego.
Jak cherry-picknąć wiele commitów?
Trzy kształty, w kolejności od najczęstszej potrzeby:
# 1. Lista jawna — w kolejności, w jakiej je wypiszesz
git cherry-pick 1a2b3c4 5d6e7f8
# 2. Zakres — wszystko po A aż do B włącznie
git cherry-pick A..B
# 3. Zakres razem z A
git cherry-pick A^..B Rozróżnienie A..B vs A^..B to klasyk zaskoczenia: A..B wyklucza A. Jeśli wizualizujesz zakres z git log i pickujesz oldest..newest, po cichu pomijasz najstarszy commit. Gdy celem jest „kilka najstarszych, po kolei”, napisz oldest^..newest i off-by-one znika.
Żeby złożyć kilka picków w jeden commit zamiast trzech, stage’uj bez commitowania przez -n / --no-commit, a potem commitnij raz:
git cherry-pick -n 1a2b3c4 5d6e7f8
git commit -m "Backport: payment retry fixes" Czemu git cherry-pick nie działa?
Cztery prawdziwe przyczyny, w kolejności częstości:
1. Pick zatrzymał konflikt. Git aplikuje patch, trafia na linię zmienioną na obu gałęziach i pauzuje w pół sekwencji:
# rozwiąż pliki, potem:
git add <resolved-files>
git cherry-pick --continue # albo --abort, by wrócić do stanu sprzed picka --continue nie jest opcjonalne ani dorozumiane — dopóki go nie odpalisz, siedzisz w zapauzowanej sekwencji cherry-pick i git status będzie ci to w kółko powtarzał.
2. Pick jest pusty („The previous cherry-pick is now empty”). Zmiana już istnieje na tej gałęzi — zwykle po wcześniejszym picku albo skwaszonym merge. Pomiń przez git cherry-pick --skip albo wymuś pusty commit przez --allow-empty, jeśli naprawdę potrzebujesz znacznika.
3. Commit jest merge commitem. Merge ma dwóch rodziców, więc „aplikuj ten diff” jest niejednoznaczne — git odmawia, zamiast zgadywać. Powiedz, względem którego rodzica liczysz diff:
git cherry-pick -m 1 <merge-sha> # parent 1 = gałąź, *do której* mergowano 4. Złe drzewo robocze albo detached HEAD. Pick ląduje tam, gdzie wskazuje HEAD. git branch --show-current przed pickiem; jeśli nie wypisze nic, jesteś w detached HEAD i commit zostanie sierotą po przeskoku gdzie indziej.
Cherry-pick vs merge vs rebase: co kiedy?
| Komenda | Co ląduje na celu | Historia | Kiedy użyć |
|---|---|---|---|
git cherry-pick <sha> | Tylko wskazane commity | Kopia, nowe SHA | Konkretny fix musi się przenieść teraz |
git merge <branch> | Wszystko z gałęzi | Merge commit albo fast-forward | Chcesz całą gałąź, z widoczną dywergencją |
git rebase <base> | Wszystkie commity gałęzi, odtworzone | Liniowa, przepisane SHA | Chcesz gałąź jako czysty liniowy ciąg |
git revert <sha> | Odwrotność commita | Dokłada commit cofający | Zalądowany commit musi zniknąć ze wspólnej historii |
Zasada w jednym zdaniu: cherry-pick przenosi wybór; merge i rebase przenoszą wszystko. Sięganie po cherry-pick, żeby „zsynchronizować” się z gałęzią, to znak, że naprawdę chcesz merge — a jeśli gałąź to main twojego forka kontra upstream, pełną rutynę opisuje synchronizacja forka z upstreamem, krok po kroku.
Jeden nawyk do pominienia: cherry-pickowanie tego samego commita do kilku gałęzi na stałe. Każdy przyszły fix na gałęzi źródłowej wymaga kolejnego picka, a gałęzie w końcu się rozjadą. Backporty na gałęzie release to normalny wzorzec; wieczny równoległy wszechświat — nie.
Workflow cherry-pick w pigułce
git log <source-branch> --oneline -5 # znajdź SHA(-e)
git switch <target-branch> # wyląduj we właściwym miejscu
git cherry-pick A^..B # zakres, lista albo pojedynczy SHA
# przy konflikcie: rozwiąż → git add → git cherry-pick --continue
git log -1 --stat # potwierdź, co wylądowało Znajdź, przełącz, pickuj, zweryfikuj. Ta komenda ma opinię niebezpiecznej, której nie zasłużyła — diff albo się aplikuje, albo zatrzymuje się i mówi ci czemu. Jedyny naprawdę destrukcyjny błąd to pick w złą gałąź, a git log -1 przed pushem sprawia, że trudno go przeoczyć.
— mrsaynothing
Get the next one by email
One email per post. No spam, no algorithms.
what is this?Cron vs timery systemd: co wybrać?
Podobają się teksty? Tak buduję zawodowo. zatrudnij mnie