Пошук уроків, статей та іншого контенту
Відпрацюєте розв’язання конфліктів, продовження, пропуск і скасування операції cherry-pick.
git cherry-pick переносить зміни з одного коміту в поточну гілку, створюючи новий коміт. Якщо Git не може автоматично застосувати зміни, операція зупиняється в стані конфлікту.
Типова послідовність така:
Запустити cherry-pick.
Отримати повідомлення про конфлікт.
Переглянути файли з конфліктами.
Вручну виправити їхній вміст.
Позначити конфлікти як розв’язані через git add.
Продовжити операцію командою git cherry-pick --continue.
Поки операція не завершена, не варто перемикатися на іншу гілку або запускати інші операції, які змінюють стан репозиторію.
Нехай у гілці feature є коміт, який змінює той самий рядок, що й коміт у гілці main.
# Створюємо тестовий репозиторій
mkdir cherry-pick-demo
cd cherry-pick-demo
git init -b main
# Налаштовуємо автора комітів і редактор повідомлень
git config user.name "Developer"
git config user.email "developer@example.com"
git config core.editor true
# Створюємо початковий файл
printf "Статус: чернетка\n" > status.txt
git add status.txt
git commit -m "Додає початковий статус"
# Створюємо гілку з власною зміною
git switch -c feature
printf "Статус: готово для перевірки\n" > status.txt
git add status.txt
git commit -m "Оновлює статус у feature"
# Повертаємося до main і змінюємо той самий рядок
git switch main
printf "Статус: схвалено\n" > status.txt
git add status.txt
git commit -m "Оновлює статус у main"
# Намагаємося перенести коміт із feature
git cherry-pick featureОстання команда зупиниться з повідомленням про конфлікт. Git також покаже файли, які не вдалося об’єднати.
Перевірити стан репозиторію можна командою:
git statusУ результаті буде приблизно така інформація:
You are currently cherry-picking a commit.
(fix conflicts and run "git cherry-pick --continue")
(use "git cherry-pick --skip" to skip this patch)
(use "git cherry-pick --abort" to cancel the cherry-pick operation)
Unmerged paths:
both modified: status.txtВідкрийте файл status.txt. Git додасть до нього спеціальні маркери:
<<<<<<< HEAD
Статус: схвалено
=======
Статус: готово для перевірки
>>>>>>> 6f3a2c1Маркери означають:
<<<<<<< HEAD — початок версії з поточної гілки, у цьому випадку main;
======= — роздільник між двома версіями;
>>>>>>> ... — кінець версії з коміту, який переноситься;
текст між маркерами потрібно проаналізувати та відредагувати.
Git не визначає, який варіант є правильним. Це рішення приймає розробник.
Наприклад, можна залишити зміст із коміту feature:
Статус: готово для перевіркиАбо об’єднати інформацію вручну:
Статус: схвалено, перевірку завершеноПісля редагування у файлі не повинно залишитися маркерів <<<<<<<, ======= і >>>>>>>.
Після виправлення файлу потрібно додати його до індексу:
git add status.txtЦе повідомляє Git, що конфлікт у файлі розв’язано. Перевірити стан можна ще раз:
git statusЯкщо всі конфлікти розв’язані, продовжте операцію:
git cherry-pick --continueGit створить новий коміт у поточній гілці main. Цей коміт матиме зміни з feature, але буде окремим комітом з іншим ідентифікатором.
Повний фрагмент розв’язання для прикладу:
# Перезаписуємо файл фінальним варіантом
printf "Статус: схвалено, перевірку завершено\n" > status.txt
# Позначаємо конфлікт як розв’язаний
git add status.txt
# Продовжуємо перерваний cherry-pick
git cherry-pick --continue
# Перевіряємо історію
git log --oneline --decorate --graph --allЯкщо редактор повідомлень не налаштований автоматично, під час git cherry-pick --continue Git може відкрити редактор для підтвердження повідомлення коміту. Збережіть повідомлення та закрийте редактор.
Перед git add корисно перевірити, що маркери конфлікту видалені:
grep -nE '^(<<<<<<<|=======|>>>>>>>)' status.txtЯкщо команда нічого не вивела, у файлі немає стандартних маркерів конфлікту.
Також перегляньте підготовлені зміни:
git diff --cachedЦе важливо, оскільки git add додає до індексу саме поточний вміст файлу. Якщо випадково залишити неправильний текст або маркер конфлікту, Git не зможе визначити помилку самостійно.
Іноді зміни з коміту вже є в поточній гілці або цей коміт більше не потрібен. У такому разі поточний коміт можна пропустити:
git cherry-pick --skipПропуск означає, що Git не створюватиме коміт для поточної операції cherry-pick.
Найчастіше --skip використовується під час перенесення кількох комітів:
git cherry-pick feature~2 feature~1 featureЯкщо під час перенесення одного з них виник конфлікт, його можна:
розв’язати та виконати git cherry-pick --continue;
пропустити та виконати git cherry-pick --skip.
Після --skip Git спробує перейти до наступного коміту в послідовності.
Не використовуйте --skip, якщо зміни потрібні, але конфлікт ще не розв’язано. У такому випадку зміни поточного коміту просто не потраплять до гілки.
Якщо конфлікт складний, було обрано неправильний коміт або перенесення більше не потрібне, операцію можна повністю скасувати:
git cherry-pick --abortПісля цього Git:
припинить поточний cherry-pick;
видалить стан незавершеної операції;
поверне поточну гілку до стану, який був до запуску cherry-pick.
Приклад:
# Скасовуємо поточну операцію
git cherry-pick --abort
# Перевіряємо стан репозиторію
git status--abort скасовує саме поточний cherry-pick, а не всі коміти, які були створені раніше.
Після ручного об’єднання може виявитися, що всі зміни коміту вже присутні в поточній гілці. Тоді Git повідомить, що коміт став порожнім.
У такій ситуації зазвичай потрібно пропустити його:
git cherry-pick --skipЯкщо ж порожній коміт має бути збережений для історії, можна створити його вручну:
git commit --allow-empty -m "Зберігає порожній cherry-pick"Для звичайного перенесення змін достатньо --skip.
Коли cherry-pick зупинився через конфлікт, дійте так:
# 1. Переглянути стан
git status
# 2. Відкрити файли з конфліктами та виправити їх
# 3. Додати кожен виправлений файл
git add path/to/file
# 4. Перевірити підготовлений результат
git diff --cached
# 5. Продовжити операцію
git cherry-pick --continueЯкщо поточний коміт не потрібен:
git cherry-pick --skipЯкщо потрібно повернутися до стану до початку операції:
git cherry-pick --abortgit cherry-pick --continue без git addРедагування файлу саме по собі не повідомляє Git, що конфлікт розв’язано. Спочатку потрібно додати файл:
git add path/to/file
git cherry-pick --continueGit може прийняти файл після git add, навіть якщо в ньому залишилися маркери конфлікту. Завжди перевіряйте фінальний текст файлу перед продовженням.
Команда git add додає поточний вміст файлу без оцінки його правильності. Перевіряйте зміни через:
git diff --cached--abort після завершення операціїgit cherry-pick --abort працює лише для незавершеної операції. Якщо cherry-pick уже завершився і створив коміт, для скасування цього коміту потрібен інший підхід, а не --abort.
Якщо конфліктів кілька, потрібно виправити кожен файл, додати кожен файл через git add, а вже потім виконати --continue.
Конфлікт під час cherry-pick означає, що Git не зміг автоматично об’єднати зміни.
Конфліктні файли потрібно відредагувати вручну та видалити маркери конфлікту.
Після виправлення використовуйте git add.
Для продовження операції використовуйте git cherry-pick --continue.
Щоб пропустити поточний коміт, використовуйте git cherry-pick --skip.
Щоб повністю скасувати незавершений cherry-pick, використовуйте git cherry-pick --abort.
Перед продовженням перевіряйте результат через git status і git diff --cached.