Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке git cherry-pick і коли його використовувати?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`git cherry-pick`** копіює конкретний коміт з іншої гілки і застосовує його до поточної як новий коміт з новим хешем. Використовуй для hotfix, бекпортів або коли потрібен один коміт з feature-гілки без злиття всього іншого. **Головне:** копіює diff, а не всю історію гілки.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`git cherry-pick`** копіює конкретний коміт з однієї гілки і застосовує його до поточної гілки як новий коміт. ## Теорія ### TL;DR - Cherry-pick - це як зірвати одну вишню з дерева, не трясучи весь кущ: береш рівно той один коміт, нічого зайвого. - Створює **новий коміт** з тими самими змінами, повідомленням і автором, але з новим хешем і твоєю гілкою як батьківською. - Головна різниця від merge: merge тягне всю історію гілки, cherry-pick бере diff тільки одного коміту. - Правило вибору: потрібно 1-3 коміти вибірково? Cherry-pick. Більше 5? Краще merge або rebase. ### Швидкий приклад ```bash # В main є bugfix, develop відстає git log --oneline main # a1b2c3d Fix login crash <- потрібне це # f4e5d6c Initial commit git checkout develop git cherry-pick a1b2c3d git log --oneline develop # b7c8d9e Fix login crash <- новий хеш, ті самі зміни # f4e5d6c Initial commit ``` Новий коміт на `develop` має той самий message і diff, але інший хеш. Оригінальний коміт залишається на `main` без змін. ### Як працює cherry-pick Git витягує diff з цільового коміту (точний патч змін) і застосовує його до робочої директорії через three-way merge. Якщо все підходить чисто, Git робить коміт автоматично, зберігаючи оригінального автора, дату і повідомлення. Якщо є конфлікти, зупиняється і дає їх вирішити. Саме через three-way merge cherry-pick справляється з переміщеними рядками краще ніж звичайний `git apply`. ### Коли використовувати - **Security hotfix на release-гілку**: патч є в `main`, продакшн на `release/v4.17`, і потрібно доставити один коміт туди прямо зараз. - **Бекпорт конкретного bugfix**: стабільна гілка отримує одне виправлення з `main` без незакінчених фіч. - **Витягнути один коміт з feature-гілки**: решта фічі не готова, але один коміт вже можна шипити. - **Коли не варто**: якщо потрібно 5+ комітів. Cherry-pick великого діапазону створює дублікати в історії і ускладнює майбутні merge. Використовуй `git merge` або `git rebase`. ### Типові помилки **Помилка 1: Cherry-pick merge-коміту без `-m`** ```bash git cherry-pick M # fatal: commit M is a merge but no -m option given ``` Merge-коміт має двох батьків. Git не знає, з якого боку брати diff. Виправлення: ```bash git cherry-pick -m 1 M # -m 1 = перший (mainline) батько ``` **Помилка 2: `git commit` після конфлікту замість `--continue`** ```bash # Вирішив конфлікт, і потім: git add . git commit -m "Fixed" # Неправильно - губляться метадані cherry-pick # Правильно: git add . git cherry-pick --continue ``` **Помилка 3: Неправильний синтаксис діапазону** ```bash git cherry-pick A..C # Застосовує B і C, пропускає A git cherry-pick A^..C # Застосовує A, B і C - це зазвичай і потрібно ``` Діапазон `A..C` виключає `A`. Додай `^`, щоб включити його. **Помилка 4: Короткий хеш у великих репозиторіях** У репозиторіях з довгою історією (як Linux kernel) короткі хеші можуть збігатися. Перевіряй перед cherry-pick: ```bash git log --oneline | grep a1b2c3 git cherry-pick a1b2c3d4e5f6 # використовуй повний хеш якщо є сумніви ``` ### Де зустрічається - **Kubernetes**: cherry-pick патчі безпеки (CVE) з `main` на `release-1.28` без зайвих змін. - **Node.js**: застосовує виправлення вразливостей у crypto до стабільної `v18.x` з `main` (наприклад, реліз v18.17.1). - **React**: портує точкові виправлення продуктивності з `canary` на `stable/18`. - **Linux kernel**: бекпортить виправлення драйверів на стабільні гілки діапазонами комітів. ### Питання на співбесіді **Q:** Яка різниця між `git cherry-pick` і `git revert`? **A:** Cherry-pick застосовує коміт вперед, додаючи його зміни до гілки. Revert створює новий коміт, що скасовує зміни попереднього. Revert безпечніший на спільних гілках, бо не переписує історію. **Q:** Як cherry-pick-нути діапазон комітів включно з першим? **A:** `git cherry-pick A^..B`. Синтаксис `A..B` виключає `A`, тому додаєш `^` щоб включити його. **Q:** Що відбувається з автором і датою оригінального коміту? **A:** Вони зберігаються в новому коміті. Committer і committer date відображають тебе і поточний час. **Q:** Коли cherry-pick спрацює там, де `git apply` впаде? **A:** Cherry-pick використовує three-way merge, тому обробляє випадки де навколишній код змістився або переїхав. `git apply` - це простий патч, який падає якщо рядки контексту не збігаються точно. **Q:** Чому в монорепо зі строгим відстеженням залежностей команди можуть надавати перевагу cherry-pick над merge для hotfix? **A:** Merge тягне весь граф гілки, додаючи шум в історію залежностей і ускладнюючи роботу автоматизованих сканерів. Cherry-pick копіює тільки diff, тримаючи граф комітів лінійним і зміну прив'язаною до одної точки. ## Приклади ### Базовий: Hotfix на release-гілку ```bash # Security fix потрапив в main git checkout main git log --oneline -3 # a1b2c3d Fix: validate req.body size (prevents DoS) # ... # Застосовуємо на production release-гілку git checkout release/v4.17 git cherry-pick a1b2c3d # Перевіряємо git log --oneline -2 # f9e8d7c Fix: validate req.body size (prevents DoS) # 3a2b1c0 Previous release commit ``` Одна команда, один коміт. Release-гілка отримує виправлення без решти змін з `main`. Це найпоширеніший сценарій cherry-pick у продакшн-кодових базах. ### Проміжний: Вирішення конфлікту під час cherry-pick ```bash git checkout feature-stable git cherry-pick b2c3d4e # CONFLICT (content): Merge conflict in src/auth.js # Відкрий src/auth.js, вирісши маркери конфлікту # Потім: git add src/auth.js git cherry-pick --continue # [feature-stable e5f6g7h] Add token expiry check ``` Якщо передумав - `git cherry-pick --abort` повертає гілку до стану до початку операції. Я сам кілька разів ішов на abort, коли конфлікт ставало зрозуміло: коміт залежить від змін, яких у цільовій гілці просто ще немає.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.