Wróć do bloga

Git cherry-pick: wiele commitów, gałęzie, konflikty

12 września 2026

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 main już 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 --stat potwierdza, 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?

KomendaCo ląduje na celuHistoriaKiedy użyć
git cherry-pick <sha>Tylko wskazane commityKopia, nowe SHAKonkretny fix musi się przenieść teraz
git merge <branch>Wszystko z gałęziMerge commit albo fast-forwardChcesz całą gałąź, z widoczną dywergencją
git rebase <base>Wszystkie commity gałęzi, odtworzoneLiniowa, przepisane SHAChcesz gałąź jako czysty liniowy ciąg
git revert <sha>Odwrotność commitaDokłada commit cofającyZalą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.

self-hosted · no third parties · one-click unsubscribe

what is this?

Cron vs timery systemd: co wybrać?

Podobają się teksty? Tak buduję zawodowo. zatrudnij mnie