Короткий зміст уроку, основні інструкції для командного рядка, корисні посилання та поради. Команда git pull з прапорцем --rebase не призводить до створення мердж комміта у гілці. Найкраще завжди кулитися з прапорцем -- rebase Щоб щоразу не писати прапорець --rebase у команді git pull, можна один раз прописати налаштування в конфігах Як виконати ребейз При цьому HEAD гілки перенесеться так, ніби ми тільки-но створили гілку від свіжопідтягнутого майстра 1. Чиста історія Перший погляд – історію переписувати не можна. Використовуємо тільки Мерджі, так історія виходить "чесна" Другий погляд - історію переписувати можна і потрібно, щоб вона була чистішою і красивішою Третій погляд – до пуша гілки переписувати історію можна, після пуша – ні. Це потрібно, щоб не завдавати незручностей колегам (розберемо ці ситуації в окремому уроці) Який підхід вибрати – вирішувати нам самим. Багато залежить від команди та проекту, в яких ми працюємо Прикладом однієї з крайнощів у підходах до історії коммітів - жодного мердж-комміта у майстрі. Усі комміти йдуть один за одним, поділу на гілки немає Виникають з тих же причин, що і за інших операцій: мердж, копіювання коммітів та інше. Вирішуються аналогічно - спочатку резолвімо конфлікти, потім завершуємо ребейз командою Також можна скасувати процес ребейза командою Дивіться відео на початку сторінки та знайдете всі відповіді ;-) Дякую за увагу і до зустрічі! Командою git rebase, немов небезпечним заклинанням, часто лякають новачків. Насправді вона може значно полегшити життя команді розробників, якщо використовувати її правильно. У цій статті проводиться порівняння команди git rebase зі схожою командою git merge та описуються всі можливі ситуації, в яких доречно включити перебазування у стандартний робочий процес Git. Насамперед потрібно розуміти, що команда git rebase допомагає вирішити ту саму проблему, що й команда git merge. Обидві команди призначені для включення змін з однієї гілки до іншої, але роблять це по-різному. Уявіть, що ви почали працювати над новою функціональною можливістю в окремій гілці, після чого інший учасник команди додає нові комміти до головної гілки main . Виникає історія форків, знайома кожному, хто використовував Git для спільної роботи. А тепер припустимо, що нові комміти в головній гілці main зачіпають функцію, над якою ви працюєте. Для включення нових коммітів у свою функціональну гілку feature можна використовувати два варіанти: злиття або перебазування. Найпростіше злиття гілки main у функціональну гілку виконується за допомогою наступної команди: За бажанням цей код можна записати в один рядок: Ця операція створює у гілці feature новий «комміт злиття», що пов'язує історії обох гілок. Структура гілок виглядатиме так: Злиття (merge) - це чудова неруйнівна операція. Існуючі гілки не змінюються. Ця операція дозволяє уникати потенційних проблем, пов'язаних із виконанням команди rebase (і наведених нижче). З іншого боку, це означає, що кожного разу, коли вам буде необхідно включити вищестоящі зміни, у функціональну гілку feature буде потрапляти зовнішній коміт злиття. Якщо робота в головній гілці main ведеться активно, історія вашої функціональної гілки швидко засмічиться.Хоча цю проблему можна усунути, використовуючи просунуті варіанти команди git log, іншим розробникам буде важко розібратися в історії проекту. Замість злиття можна виконати перебазування функціональної гілки feature на головну гілку main за допомогою наступних команд: В результаті вся функціональна гілка feature виявиться поверх головної гілки main, включаючи все нові комміти в гілці main. Якщо замість команди merge при коммітах використовується rebase, ця команда перезаписує історію проекту, створюючи нові комміти для кожного комміту у вихідній гілці. Головна перевага rebase — чистіша історія проекту. По-перше, ця команда усуває непотрібні коміти злиття, необхідні для git merge. По-друге, як показано на малюнку вище, команда rebase створює ідеальну лінійну історію проекту - ви зможете відстежити функціонал до початку проекту без будь-яких форків. Це спрощує навігацію в проекті за допомогою таких команд, як git log, git bisect та gitk. Однак така бездоганна історія коммітів вимагає певних жертв: жертвувати доводиться безпекою та відстежуваністю. Якщо не слідувати Золотому правилу Rebase, перезапис історії проекту може призвести до катастрофічних наслідків для спільних робочих процесів. Крім того, при виконанні rebase втрачається контекст, доступний у коміті зі злиттям: ви не зможете побачити, коли вищезгадані зміни були включені у функціонал. Інтерактивна операція rebase дозволяє змінювати комміти при переміщенні в нову гілку.Цей варіант надає більше можливостей, ніж автоматичне виконання rebase, оскільки дає повний контроль над історією коммітів гілки. Зазвичай його використовують для очищення заплутаної історії перед тим, як зливати функціональну гілку в головну гілку main . Щоб запустити інтерактивне перебазування, передайте параметр i команді git rebase : Відкриється текстовий редактор. У ньому буде перераховано всі комміти, підготовлені до переміщення: Цей список точно відображає, як виглядатиме гілка після перебазування. Змінюючи команду pick та (або) порядок коммітів, ви можете надати історії гілки потрібного вигляду. Так, якщо другий коміт містить виправлення невеликої проблеми в першому, їх можна поєднати за допомогою команди fixup : Коли ви збережете та закриєте файл, Git виконає перебазування відповідно до ваших вказівок. Історія проекту потім набуде наступного вигляду: Вилучення незначних коммітів допомагає швидше розібратися в історії функціональної гілки. Команда git merge просто не в змозі це зробити. Розібравшись із можливостями rebase, необхідно насамперед зрозуміти, коли цю команду не потрібно використовувати. Золоте правило для команди git rebase - ніколи не використовувати її в публічних гілках. Наприклад, уявіть, що станеться, якщо ви виконаєте rebase головної гілки main на свою функціональну гілку feature . Перебазування переміщає всі комміти гілки main в кінець гілки feature. Проблема в тому, що це відбувається тільки в вашому репозиторії, тоді як інші розробники продовжують працювати з вихідною гілкою main . Оскільки в результаті перебазування створюються абсолютно нові комміти, Git вважатиме, що історія вашої головної гілки main розійшлася з рештою. Єдиний спосіб синхронізувати дві основні гілки main - виконати їхнє зворотне злиття. Це призведе до додаткового коміту злиття. і двом наборам коммітів, які містять одні й самі зміни (вихідні зміни та зміни з вашої гілки після rebase). Чи потрібно говорити, що ситуація вийде вкрай заплутана? Тому перед виконанням команди git rebase слід переконатися, що поточна гілка не переглядає хтось інший. Якщо в ній справді ведеться робота, припиніть будь-які дії та подумайте, як можна внести зміни неруйнівним способом (наприклад, за допомогою команди git revert). В інших випадках ви можете вільно перезаписувати історію за потреби. Git заблокує спробу помістити перебазовану гілку main назад у віддалений репозиторій, оскільки вона вступить у конфлікт із віддаленою гілкою main . Але цю операцію можна виконати примусово, додавши прапорці --force : При цьому віддалена гілка main буде відповідати гілці у вашому репозиторії після rebase. Зрештою плутатися почнуть і ваші колеги. Тому будьте уважні та використовуйте цю команду тільки в тому випадку, якщо повністю розумієте, чого хочете досягти. Одна з небагатьох ситуацій, що потребують форсованого приміщення коду, — це локальне очищення після приміщення приватної функціональної гілки у віддалений репозиторій (наприклад, для створення резервної копії). Це рівноцінно заяві: «Ой, адже я не хотів відправляти вихідну версію цієї функціональної гілки. Найкраще візьміть поточну версію». Тут також важливо, щоб ніхто після коммітів не розпочав роботу з вихідної версії функціональної гілки. Перебазування можна використовувати при роботі з Git у тому обсязі, який підходить команді. У цьому розділі ви дізнаєтеся про переваги перебазування різних етапах розробки функцій продукту. У будь-якому робочому процесі із застосуванням команди git rebase спочатку потрібно створити окрему гілку для кожної функції. Отримана структура гілок необхідна для безпечного перебазування: Один із найефективніших сценаріїв перебазування в робочому процесі – це очищення локальних функціональних гілок, у яких ще ведеться робота. Якщо періодично проводити інтерактивне перебазування, жоден коміт у вашій гілці не втратить сенсу. Ви можете бути впевнені, що ваш код не розпадеться на ізольовані комміти. Якщо це станеться, ситуацію завжди можна буде виправити. При використанні команди git rebase є два варіанти для нового положення гілки: гілка для функціональної гілки (наприклад, гілка main ) або більш ранній коміт у функціональній гілці. Перший варіант описувався в прикладі розділу Інтерактивне перебазування. Другий варіант зручний, коли потрібно виправити лише кілька недавніх коммітів. Наприклад, наступна команда запускає інтерактивну операцію rebase лише трьох останніх коммітів. Вказавши HEAD~3 як нове положення, ви не переміщаєте гілку як таку, а лише інтерактивно переписуєте 3 наступні коміти. Слід зазначити, що при цій операції вищі зміни не включаються у функціональну гілку. Якщо за допомогою цього способу ви хочете переписати всю функціональну гілку, то знайти початкове положення функціональної гілки допоможе команда git merge-base . Наступна команда повертає ID комміта початкового положення, який можна передати в команду git rebase : Таке використання інтерактивної операції rebase відмінно допоможе включити git rebase в робочий процес, оскільки торкнеться лише локальних гілок. Інші розробники побачать лише закінчену версію з простою і відстежуваною історією функціональної гілки. Повторимо, що це працює тільки для приватних функціональних гілок. Якщо ви працюєте в одній функціональній гілці з іншими розробниками, вона є публічної та переписувати її історію заборонено. Варіанту очищення локальних коммітів з інтерактивним використанням rebase за допомогою команди git merge не існує. У розділі Огляд основних моментів розглядалося включення вищих змін із головної гілки main у функціональну гілку за допомогою команди git merge або git rebase. Операцію злиття можна виконувати безпечно, оскільки зберігається вся історія репозиторію. При виконанні перебазування створюється лінійна структура: функціональна гілка переміщається до кінця гілки main . У цьому випадку команда git rebase використовується так само, як і локальне очищення (яку можна здійснити одночасно), але при її виконанні включаються зміни з головної гілки main . Пам'ятайте, що ще можна виконувати rebase у віддалену гілку, відмінну від гілки main . Наприклад, при спільній роботі над функціональною можливістю з іншим розробником, коли потрібно включити його зміни до вашого репозиторію. Наприклад, якщо ви разом з розробником Джоном додавали комміти у гілку feature, то після отримання віддаленої гілки feature з репозиторію Джона ваш репозиторій може виглядати так: З таким розгалуженням можна працювати так само, як і при включенні вищестоящих змін з гілки main: або виконати злиття в локальну гілку feature для гілки john/feature, або виконати перебазування локальної гілки feature на кінець гілки john/feature. Зверніть увагу: таке перебазування не порушує «золоте правило», оскільки переміщаються лише комміти вашої гілки feature , тоді як попередні елементи залишаються недоторканими. По суті, ця операція дозволяє лише додати ваші зміни до напрацювань Джона. Найчастіше це простіше, ніж виконувати синхронізацію із віддаленою гілкою за допомогою комміту злиття. За промовчанням команда git pull виконує злиття. Однак, якщо передати їй параметр --rebase , буде виконано перебазування для віддаленої гілки. Якщо під час перевірки коду використовуються пул-реквести, не використовуйте команду git rebase після створення пул-реквесту. Відразу після створення пул-реквесту інші розробники зможуть бачити ваші комміти, тобто ваша гілка стане публічної. У разі перезапису її історії Git та ваші колеги не зможуть відслідковувати наступні комміти у функціональну гілку. Всі зміни, зроблені іншими розробниками, потрібно додавати командою git merge, а не git rebase. Тому гарною ідеєю є очищення коду за допомогою інтерактивної операції. перед створенням пул-реквесту. Після схвалення функціональної гілки колегою можна перебазувати її на кінець гілки main , а потім використовувати команду git merge для включення функціональної гілки в основну базу коду. Це схоже на включення вищих змін у функціональну гілку, але оскільки переписувати комміти в головній гілці main заборонено вам доведеться використовувати для включення функціональної гілки команду git merge . Виконуючи перебазування перед злиттям, ви забезпечуєте прискорене злиття та ідеальну лінійну історію. Такий підхід також дозволяє склеювати будь-які наступні комміти, додані до закриття запиту pull. Якщо ви ще не звикли працювати з командою git rebase, завжди можна виконати rebase у тимчасову гілку. У такому разі, якщо ви випадково заплутаєте історію функціональної гілки, завжди можна буде перейти у вихідну гілку і спробувати знову. Наприклад: Тепер у вас достатньо інформації, щоб почати використовувати rebase для своїх гілок. Якщо ви надаєте перевагу чистій лінійній історії без непотрібних коммітів злиття, використовуйте команду git rebase замість git merge при включенні змін з іншої гілки. Але якщо вам потрібно зберегти повну історію проекту та уникнути перезапису публічних коммітів, скористайтесь командою git merge. Тепер ви можете не тільки застосувати злиття, але й оцінити переваги команди git rebase - обидва варіанти ефективні у роботі. Знайомимо з git rebase: розповідаємо про переваги команди та показуємо, у яких випадках її варто використати і чому. Ця інструкція є частиною курсу «Введення в Git». Дивитись весь курс Rebase (перебазування) — один із способів git, що дозволяє об'єднати зміни двох гілок. Цей спосіб має перевагу перед merge (злиття) — він дозволяє переписати історію гілки, надавши історії того вигляду, який нам потрібен. Приклад роботи git rebase У цій інструкції ми познайомимо вас ближче з командою git rebase, розповімо про переваги та тонкощі роботи з нею, покажемо, в яких випадках її варто використовувати і чому. З документації — це накладення комітів поверх іншого базового коміту. Під базовим розуміється той коміт, якого застосовуються коммиты обраної гілки. Перший аргумент обов'язковий (upstream) – це базовий коміт, до якого застосовуються коміти вибраної гілки. Другий аргумент можна не ставити, якщо HEAD вказує на гілку, яка буде перебазована нами. Щоб розуміти процес перебазування, звернімося до рисунка 1. У нас є дві гілки. master і my_branch. Ми знаходимося на гілці my_branch (HEAD вказує на гілку my_branch). Виконуємо команду: Після цього git видалить і послідовно перемістить коміти C, D, F з гілки my_branch у гілку master - Спершу C, потім D і F. Нові комміти C', D', F' повністю ідентичні віддаленим, змінюється тільки хеш. Спочатку для гілки my_branch базовим коммітом був B, але потім став комміт E. Це і є процес під назвою перебазування. Перебазування в git використовується для додання лінійності історії гілки, щоб зручно відстежувати зміни, або для оновлення гілки розробки останніми змінами з основної гілки.Також є й інші варіанти використання – за допомогою інтерактивного режиму та параметра -onto. Після того, як ми використовували команду git rebase, можна перемотати гілку master командою git merge: До команди злиття можна додати прапор або -ff (fast-forward merge), щоб не створювати комміт злиття, або додати -no-ff - Для його створення. Створення комміту злиття допомагає визначити, коли гілки об'єдналися і які коміти тематичної гілки було зроблено. Злиття перебазованої гілки.
Коли роботу з тематичною гілкою закінчено, видаляємо її: Це призведе до закінченого виду історії, коли ми впровадили зміни з тематичної гілки в основну частину проекту. Лінійна історія майстер-гілки.
Так як git rebase послідовно перезастосовує комміти, можуть виникнути конфлікти злиття (merge conflicts). Перша причина появи конфлікту — об'єднання коммітів, що містять зміни в одних і тих самих файлах. Друга причина – кілька людей змінюють однаковий файл на одній розшарованій гілці. Щоб дізнатися, які файли мають конфліктуючі зміни, перевіримо статус. Нам буде запропоновано вирішити конфліктні комміти, потім помітити їх вирішеними: Далі потрібно продовжити перебазування: Або ще відкотити зміни - повернутися до стану до використання команди rebase. Є і третій варіант із перезапуском кроку та перезавантаженням процесу перебазування: Але будьте обережні, skip пропустить (видалити) конфліктний коміт. Старт за кілька хвилин, зручне керування сервісами та миттєве масштабування. Інтерактивний режим rebase використовується для перезапису історії шляхом зміни самих коммітів, а також інформації в них. Перехід до інтерактивного режиму перебазування робиться за допомогою прапора -i або interactive. Виконання цієї команди створить список коммітів у хронологічному порядку додавання, щоб користувач міг за бажанням відредагувати їх перед наступним перебазуванням. Далі ми розглянемо докладніше, як це відбувається. Наприклад, створена гілка master з п'ятьма коммітами: Поставлено два завдання: Для цього ми вмикаємо інтерактивний режим rebase. У ньому можна зазначити певну кількість коммітів для зміни. Щоб це зробити, необхідно передати в аргумент коміт, що передує тому, який ми будемо змінювати (в даному випадку це fmjgyu6), або задати “HEAD~[x]”, де замість [x] — необхідне число коммітів. Відкриється текстовий редактор за промовчанням, де також буде наведено опис команд, що використовуються в інтерактивному режимі rebase: Зверніть увагу, що комміти в інтерактивному режимі розташовані в іншому порядку, від більш старого до нового. Приступимо до вирішення завдань. У результаті маємо наступний порядок коммітів: Не забуваймо зберігати зміни, як ви зазвичай робите при збереженні у текстовому редакторі. Виходимо з інтерактивного режиму закриття текстового редактора. Тепер наша гілка має вигляд: Майте на увазі, що хеш коммітів, з якими працював rebase, стануть іншими. Інтерактивний rebase - просунута версія звичайного rebase, яка дає можливість більшої взаємодії з комітом. Якщо потрібно розділити, об'єднати, видалити комміти, змінити їх опис та порядок, інтерактивний режим впорається відмінно.Якщо ж такої потреби немає, швидше використовуватиме стандартний режим rebase, у якому від користувача не потрібні зайві дії до виникнення конфліктів. Onto відноситься до можливостей, що розкривають rebase у всій красі. Ця опція дозволяє вказати комміт, з якого перебазуватимуться комміти (перший аргумент), інакше це називається нова база. Третій аргумент (branch) можна не вказувати, якщо HEAD вказує на гілку, яка буде перебазована нами. приклад Гілки master, feature-1, develop до rebase.
Нам потрібно інтегрувати зміни з гілки develop до master. Скористаємося звичайним rebase: Тоді отримаємо такий результат з двома однаковими комітами D: Гілки master, feature-1, develop після стандартного rebase.
Це сталося тому, що перебазування перезастосовувало коміти D, G, H, I, оскільки по відношенню до гілки master коміти гілки develop починаються з коміту D як коміта, що зв'язує. Тепер вирішимо завдання з інтеграцією змін з develop трохи інакше. Щоб уникнути таких випадків як із коммітом D, скористаємося новою командою: Результат проілюстровано на малюнку нижче. Гілки master, feature-1, develop після rebase з опцією onto.
При роботі з віддаленим репозиторієм у тематичній гілці, наприклад GitHub, слід бути обережним, використовуючи rebase. Як ви вже знаєте, rebase перезаписує історію, у процесі змінюються хеші коммітів, а це може призвести до конфліктів у роботі з гілкою в інших членів команди.Тому, якщо ви працюєте над тематичною гілкою не одні, варто вдатися до кількох правил для запобігання можливим проблемам. Щоб запустити свою гілку, коли git не знає, як поєднати гілки, використовується режим force: З цим режимом будуть скопійовані батьківські коміти feature на origin, покажчик переміщається, як він встановлений на локальному репозиторії. Важливо вказати ідентифікатор гілки в , інакше запушаться всі локальні гілки ориджину. А щоб витягти зміни з віддаленого репозиторію, замість звичайного pull можна використовувати режим rebase: Локальні merge комміти не утворюються, а історія виглядатиме лінійно. Нижче наведено таблицю деяких опцій, які можуть бути корисними для роботи з rebase. У цій інструкції ми розглянули, як зробити rebase гілки в git, довідалися про можливість більш просунутої маніпуляції з комітами в режимі interactive і onto, а також тонкощі, які слід дотримуватися при роботі з rebase.Вивчаємо Git. Урок 18.
Що таке git rebase
Відмінності merge та rebasegit pull --rebase
Прописуємо --rebase у конфігах
Перебазування, git rebase
Відмінності ребейза від мерджа
2. Немає мердж-коммітів
3. Комміти йдуть один за одним у логічному порядку
4. git rebase переписує історію коммітів, на відміну від git mergeРізні погляди на історію коммітів
"Плоска" історія коммітів
Конфлікти при ребейзі
Що ж вибрати?
Усі уроки курсу
Merging vs. rebasing
Conceptual overview
Пов'язані матеріали
Переміщення повного репозиторію Git
СМ. РІШЕННЯ
Вивчіть Git за допомогою Bitbucket Cloud
The merge option
git checkout feature
git merge maingit merge feature mainThe rebase option
git checkout feature
git rebase mainInteractive rebasing
git checkout feature
git rebase -i mainpick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3pick 33d5b7a Message for commit #1
fixup 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3The golden rule of rebasing
Force-pushing
# Be very careful with this command! git push --forceWorkflow walkthrough
Local cleanup
git checkout feature git rebase -i HEAD~3git merge-base feature mainIncorporating upstream changes into a feature
Reviewing a feature with pull request
Integrated an approved feature
git checkout feature
git checkout -b temporary-branch
git rebase -i main
# [Clean up the history]
git checkout main
git merge temporary-branchРезюме
Git rebase - перебазування коммітів та гілок
Вступ
Git rebase - що це
Як працює git rebase
Як використовувати git rebase
Лінійна історія - реінтеграція тематичної гілки після виконання git rebase master
git checkout master git merge my_branchgit branch -d my_branchКонфлікти
git rebase --continueХмарні сервери для будь-яких завдань
Git rebase interactive
git rebase [-i | --interactive]Як користуватися інтерактивним режимом
2hqsibn selected new method in script.js (HEAD -> master) 4kq5jn2 зміни до script.j qk01ru3 resolved conflict fmjgyu6 added new files z2zgn0c initial commit (origin/master)
git rebase -i HEAD~3
pick qk01ru3 resolved conflict pick 4kq5jn2 зміни до sсript.j pick 2hqsibn вибраний новий метод в script.js # Rebase fmjgyu6..2hqsibn on fmjgyu6 # # Commands: # p, pick edit commit message # e, edit = use commit, але stop for amending # s, squash = use commit, але meld into previous commit # f, fixup = like "squash", але discard this commit's log message # x, exec = run command (the rest of the line) using shell # b, break = stop here (continue rebase later with 'git rebase --continue') # d, drop = remove commit
reword 4kq5jn2 зміни до sсript.js pick qk01ru3 resolved conflict pick 2hqsibn selected new method in script.jsvh9xwf3 вибраний новий метод в script.js (HEAD -> master) s70zmpx resolved conflict b0jemdh changes to script.js fmjgyu6 added new files z2zgn0cЯкий режим вибрати: стандартний чи інтерактивний
Git rebase-onto
У нас є три гілки: master, feature-1, develop.
git checkout developgit rebase --onto master feature-1 developRebase віддаленого репозиторію
Pull rebase
git push origin --forcegit pull --rebase origin
Додаткові опції перебазування
Опції Пояснення -s -strategy = Використовувати стратегію злиття замість дефолтного “ort”, що змінить поведінку rebase. Докладніше у документації. -X -strategy-option = Ця опція для застосування більш ніж однієї стратегії в порядку, заданому користувачем. -x -exec Виконання однієї або більше команд-shell після кожного кроку rebase в інтерактивному режимі. Якщо виконання команди невдало, перебазування зупиниться. -no-keep-empty Чи не залишати порожні комміти. Тобто прибирати ті комміти, які нічого не змінюють по відношенню до батька. -allow-empty-message Дозволяє перебазувати порожні комміти із порожнім повідомленням. -autosquash В інтерактивному режимі бере комміти, що починаються з fixup! або squash! і ставить відповідну команду, щоб об'єднати коміт з попереднім. Щоб це значення завжди працювало за замовчуванням, можна прописати таке: Висновок
Більше матеріалів про розробку