Пошук уроків, статей та іншого контенту
Навчитеся переносити гілку на актуальний стан іншої гілки за допомогою команди rebase.
git rebasegit rebase переносить коміти поточної гілки на вершину іншої гілки.
Наприклад, маємо таку історію:
A---B---C main
\
D---E featureГілка main отримала коміт C після створення feature. Якщо виконати rebase, Git перенесе коміти D і E на актуальний стан main:
A---B---C---D'---E' feature
^
mainКоміти D' і E' містять ті самі зміни, що й D та E, але мають нові ідентифікатори. Тому rebase змінює історію комітів.
Припустімо, що:
main — основна гілка;
feature — гілка з вашою новою функціональністю;
ви працюєте у гілці feature;
зміни з main потрібно перенести у feature.
git statusПеред rebase бажано мати чисту робочу директорію:
nothing to commit, working tree cleanЯкщо є незбережені зміни, спочатку:
створіть коміт;
або тимчасово збережіть зміни за допомогою іншого механізму.
git switch featurerebase застосовується до поточної гілки. У цьому прикладі поточною має бути саме feature.
mainЯкщо main оновлюється в локальному репозиторії:
git switch main
git pullПісля цього поверніться до гілки функціональності:
git switch featurerebasegit rebase mainGit знайде коміти, які є у feature, але відсутні в main, і застосує їх поверх поточного стану main.
Після успішного виконання історія стане лінійною:
A---B---C---D'---E' feature
^
mainНижче наведено приклад у тимчасовому репозиторії:
# Створюємо тимчасову папку та переходимо до неї
mkdir rebase-demo
cd rebase-demo
# Ініціалізуємо Git-репозиторій
git init
# Налаштовуємо ім'я основної гілки та дані автора комітів
git branch -M main
git config user.name "Student"
git config user.email "student@example.com"
# Створюємо перший файл і початковий коміт
printf "# Проєкт\n" > README.md
git add README.md
git commit -m "Додати README"
# Створюємо гілку для нової функціональності
git switch -c feature
# Додаємо зміни у feature
printf "Пошук товарів\n" > search.txt
git add search.txt
git commit -m "Додати пошук товарів"
# Повертаємося в main і додаємо незалежну зміну
git switch main
printf "Версія 1.0\n" > VERSION
git add VERSION
git commit -m "Додати версію проєкту"
# Повертаємося у feature
git switch feature
# Переносимо коміт feature на актуальний стан main
git rebase main
# Переглядаємо історію комітів
git log --oneline --graph --allПісля rebase коміт із файлом search.txt буде розташований після коміту з файлом VERSION.
rebaseПід час виконання:
git rebase mainGit виконує такі кроки:
Знаходить спільний предок гілок.
Тимчасово знімає коміти поточної гілки після цього предка.
Переміщує поточну гілку на вершину main.
Застосовує зняті коміти по одному.
Створює нову історію з перенесеними комітами.
Саме тому ідентифікатори комітів після rebase можуть змінитися.
Конфлікт виникає, якщо зміни у feature і main стосуються одних і тих самих рядків або Git не може автоматично об'єднати їх.
Під час конфлікту rebase призупиниться та покаже повідомлення про конфлікт.
git statusGit також позначить конфліктні місця у файлах:
<<<<<<< HEAD
Зміни з main
=======
Зміни з feature
>>>>>>> commit-from-featureПотрібно залишити правильний варіант або об'єднати обидва варіанти вручну. Також потрібно видалити службові маркери:
<<<<<<<
=======
>>>>>>>Після виправлення конфлікту повідомте Git, що файл готовий:
git add назва-файлуЯкщо конфліктних файлів кілька, додайте кожен виправлений файл.
rebasegit rebase --continueGit спробує застосувати наступний коміт. Якщо виникне ще один конфлікт, повторіть ті самі кроки:
виправте файл;
виконайте git add;
виконайте git rebase --continue.
rebaseЯкщо ви вирішили не продовжувати операцію:
git rebase --abortGit скасує поточний rebase і поверне гілку до стану, який був до його початку.
Після успішного rebase корисно переглянути історію:
git log --oneline --graph --decorate --allТакож перевірте стан робочої директорії:
git statusПісля успішного перенесення комітів очікується чистий стан:
nothing to commit, working tree cleanrebaseОскільки rebase створює нові коміти, віддалена гілка може більше не збігатися з локальною.
Якщо гілка вже була відправлена до віддаленого репозиторію, для оновлення зазвичай використовують:
git push --force-with-lease origin featureОпція --force-with-lease безпечніша за звичайний --force: Git перевіряє, що віддалена гілка не отримала нових комітів від іншого користувача.
Переписування історії спільної гілки може завадити іншим розробникам. Тому не виконуйте rebase для гілки, якою одночасно користуються інші люди, без узгодження з командою.
rebase і mergeОбидві команди можуть перенести зміни з main у feature, але створюють різну історію.
merge створює окремий merge-коміт:
A---B---C------M feature
\ /
D---E--rebase переносить коміти на нову основу:
A---B---C---D'---E' featurerebase часто використовують, щоб перед інтеграцією зробити історію гілки лінійною та зрозумілою.
rebase не в тій гілціКоманда:
git rebase mainпереносить коміти поточної гілки на main.
Перед виконанням перевірте поточну гілку:
git branch --show-currentrebase із незбереженими змінамиНе починайте rebase, якщо робоча директорія містить незбережені зміни. Спочатку виконайте коміт або приведіть робочу директорію до чистого стану.
git addПісля виправлення конфлікту недостатньо просто зберегти файл. Потрібно додати його до індексу:
git add назва-файлу
git rebase --continuegit commit замість git rebase --continueПід час призупиненого rebase для продовження операції використовуйте:
git rebase --continueGit сам керує комітами, які переносить.
--forceКоманда:
git push --forceможе перезаписати чужі зміни у віддаленій гілці. Якщо переписування історії необхідне, безпечніше використовувати:
git push --force-with-leaseНе переписуйте історію гілок, які вже використовують інші розробники, без попереднього узгодження. Для таких гілок зазвичай безпечніше не змінювати вже опубліковані коміти.
git rebase main переносить коміти поточної гілки на вершину main.
Перед rebase потрібно перейти в гілку, яку ви оновлюєте.
Робоча директорія має бути чистою.
Під час конфлікту потрібно виправити файли, виконати git add, а потім git rebase --continue.
Щоб скасувати операцію, використовуйте git rebase --abort.
rebase переписує історію та створює нові ідентифікатори комітів.
Не використовуйте rebase для спільних опублікованих гілок без узгодження.