Cherry-pick — това е Git команда, която прилага промените от посочения комит в текущия клон, без да прехвърля цялата история на изходния клон. За разлика от merge или rebase, cherry-pick работи с всеки комит поотделно: разработчикът избира конкретен комит по хеш и прехвърля само неговите промени. Според документацията на Git (2026), cherry-pick е особено полезен за точково прехвърляне на корекции между релизни клонове, когато целият merge е излишен или опасен. Командата създава нов комит с нов хеш, но запазва оригиналното съобщение и автора.
Основно
Cherry-pick — това е командата git cherry-pick, която взема промени от съществуващ комит и ги прилага като нов комит в текущия клон. Изходният комит остава на мястото си в своя клон, а в целевия клон се създава копие на промените. Командата е полезна, когато трябва да се прехвърли конкретна корекция, без да се премества целият клон.
Синтаксис: git cherry-pick <commit-hash>. Git анализира разликата (diff) на посочения комит с неговия родител и прилага тази разлика към текущия клон. Ако са променени няколко файла — всички те се прехвърлят заедно. Командата приема и диапазони: git cherry-pick A..B — всички комити от A до B, без да включва A.
Флаговете разширяват възможностите: -n (--no-commit) прилага промените към работната директория и индекса без създаване на комит — полезно, когато трябва да се обединят промените на няколко комита в един. Флагът -x добавя в съобщението на комита ред (cherry picked from commit ...), което улеснява проследяването на произхода на промените в историята.
# Cherry-pick на единичен комит по хеш
git cherry-pick a1b2c3d
# Cherry-pick на няколко комита (последователно)
git cherry-pick a1b2c3d e4f5g6h i6j7k8l
# Cherry-pick без автоматичен комит
git cherry-pick -n a1b2c3d
# Флагът -x добавя препратка към оригиналния комит
git cherry-pick -x a1b2c3d
Основният сценарий — прехвърляне на корекции между релизни клонове. Представете си: в develop е открит и поправен критичен бъг. Релизният клон release/v2.1 вече е отделен и в него този бъг също присъства. Merge на целия develop в release би прехвърлил много неготов код, а cherry-pick на един комит с корекцията — безопасно и точно решение.
Вторият сценарий — отмяна на промени (revert) с последващо възстановяване. Ако комит е бил отменен чрез git revert, а после се окаже, че отмяната е била погрешна — cherry-pick на отменения комит възстановява промените. Това е по-коректно от отмяната на revert, тъй като не създава повторни конфликти.
Третият сценарий — обединяване на комити от различни feature клонове в един тестов клон за интеграционно тестване. Вместо да се сливат няколко незавършени клона (с недовършен код), може да се изберат само готовите комити от всеки и да се тества съвместната им работа.
Cherry-pick се различава от rebase и merge по това, че работи на ниво отделни комити, а не цели клонове. Ако rebase прехвърля всички комити на клона, а merge обединява два клона, то cherry-pick избира само необходимите. Това го прави по-точен инструмент, но и по-ръчен.
Друга разлика — авторството. При cherry-pick Git по подразбиране запазва автора на оригиналния комит (Author), но комитер (Committer) става текущият потребител. В съобщението на комита произходът може да се проследи чрез флага -x. При rebase авторът и комитерът — и двамата са текущият потребител с нов хеш.
Производителност: cherry-pick на един комит се изпълнява по-бързо от merge на два клона с голям брой комити. Но ако трябва да се прехвърлят десетки комити, по-добре е да се създаде временен клон и да се извърши rebase — това ще е по-ефективно и няма да изисква посочването на десетки хешове.
| Операция | Област на приложение | Странични ефекти |
|---|---|---|
| Cherry-pick | Отделни комити | Нов хеш, дублиране на код |
| Rebase | Всички комити на клона | Презаписване на историята, нови хешове |
| Merge | Пълно сливане на клонове | Merge комит, запазване на историята |
Няколко комита могат да бъдат прехвърлени с една команда, като се изброят техните хешове с интервал: git cherry-pick A B C. Git прилага комитите последователно в посочения ред. Ако някой от комитите предизвика конфликт, cherry-pick се преустановява и разработчикът трябва да разреши конфликта, след което да продължи с командата git cherry-pick --continue.
Диапазон на комити: git cherry-pick A..B (всички комити след A до B, без A) и git cherry-pick A^..B (всички комити от A включително до B). Диапазоните са удобни, когато трябва да се прехвърлят всички комити от един клон, но без родителска връзка — например при прехвърляне на готова фича от стар клон в нов.
Флагът --strategy определя как Git ще прилага промените. По подразбиране се използва recursive стратегия, но може да се посочи ours или theirs за автоматичен избор на страната на конфликта. Флагът --mainline се използва при cherry-pick на merge комит — указва номера на родителя (1 или 2), спрямо който се изчислява diff.
# Cherry-pick на диапазон от комити
git cherry-pick develop~5..develop~2
# Cherry-pick на merge комит (посочете родителя)
git cherry-pick -m 1 m9n0o1p
# Използване на theirs стратегия
git cherry-pick --strategy=recursive \
--strategy-option=theirs a1b2c3d
# Продължете след разрешаването на конфликта
git cherry-pick --continue
Конфликти при cherry-pick възникват, когато промените на прехвърляния комит засягат същите редове, които са били променени в целевия клон. Git преустановява изпълнението, маркира конфликтните файлове и очаква разрешаване. В статуса такива файлове се показват като both modified.
Ред на действията при конфликт: отворете конфликтния файл, намерете маркерите на конфликта (<<<<<<<, =======, >>>>>>>), редактирайте съдържанието, премахнете маркерите, изпълнете git add за разрешените файлове и стартирайте git cherry-pick --continue. Ако конфликтът е неразрешим — git cherry-pick --abort отменя целия cherry-pick, връщайки клона в изходно състояние.
Често срещан проблем: комитът вече съдържа промени, еквивалентни на съществуващите. В този случай Git съобщава „nothing to commit“ или „empty commit“ при опит за cherry-pick. Флаговете --keep-redundant-commits и --empty=keep принуждават Git да създаде празен комит за запазване на последователността, а --skip позволява да се пропусне такъв комит.
# Конфликт по време на cherry-pick — спрете
git cherry-pick a1b2c3d
# грешка: не може да приложи a1b2c3d... съобщение на комит
# Разрешете конфликта → добавете в индекса
git add src/conflicted_file.swift
git cherry-pick --continue
# Пропуснете празния комит (вече приложен)
git cherry-pick --skip
# Пълно преустановяване (abort)
git cherry-pick --abort
Първо правило: винаги проверявайте, че прехвърляният комит е самостоятелен. Ако комит A зависи от промени в комит B, който не се прехвърля, cherry-pick на A може да счупи сборката. Преди cherry-pick е полезно да проверите кои файлове е променил комитът чрез git show --stat <hash>.
Второ правило: документирайте cherry-pick. Използвайте флага -x, за да се запази в съобщението на комита препратка към изходния комит. Това ще помогне при последващ анализ на историята да се разбере откъде идва промяната. Без -x cherry-pick изглежда като обикновен комит и произходът му може да се установи само чрез git log --graph.
Трето правило: избягвайте cherry-pick между клонове, които се разминават твърде много. Ако от създаването на комита е минало много време и кодовата база се е променила съществено, конфликтите ще бъдат многобройни и сложни. В такива случаи е по-добре да се направи корекцията наново в целевия клон — това ще отнеме по-малко време от разрешаването на десетки конфликти.
Често задавани въпроси
Да зачерипикнете — да приложите промените на посочения комит в текущия клон чрез git cherry-pick. Командата създава нов комит със същите промени, но с нов хеш. Изходният комит остава без промени в своя клон. Това е алтернатива на сливането на целия клон, когато е нужен само един конкретен комит.
Cherry-pick се избира, когато трябва да се прехвърлят един или няколко конкретни комита без прехвърляне на целия клон. Merge се използва за пълно сливане на клонове. Типичният сценарий на cherry-pick — прехвърляне на багфикс от клона за разработка в релизния клон, в който останалите промени още не са готови.
Преди завършването — git cherry-pick --abort отменя операцията напълно. След успешно завършване — git revert <hash> създава комит, който отменя промените на cherry-pick. Разликата от --abort: revert не изтрива комита от историята, а създава нов отменящ комит.
Празният комит възниква, когато промените вече присъстват в целевия клон. Използвайте git cherry-pick --skip, за да пропуснете такъв комит, или git cherry-pick --keep-redundant-commits, за да създадете празен комит за запазване на последователността от хешове.
Cherry-pick прехвърля избраните комити (по един или по списък) в текущия клон. Rebase прехвърля всички комити на клона върху нова база. Cherry-pick не променя изходния клон, rebase презаписва историята. Cherry-pick е точен, но ръчен; rebase е автоматичен, но опасен за публични клонове.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също