Rebase Flow. Спосіб приготування і його підтримка в GitHub, GitLab, BitBucket

Трохи історії
В самому початку 2010 року Vincent Driessen пише чудову статтю A successful Git branching model. Для розуміння того, про що піде мова далі, зі статтею потрібно, звичайно ж, познайомитися. А для тих, кому складний мова оригінальної статті, на хабре є відмінний переклад.
З цього моменту описана модель розгалуження GitFlow, починає, що називається, розходитися по світу. Її беруть на озброєння багато команд. Автори пишуть багато статей про успішне її використанні. Вона отримує підтримку у більшості інструментів, які використовують розробники:
Git
Здається, що ідеальна модель. Бути може так воно і є, якщо у вас невелика команда, незмінний скоуп релізів, висока культура роботи з VCS. Тоді, дійсно, GitFlow може і задовольнить всі ваші потреби. Але, на жаль, описані умови підходять не всім командам і не всім проектам. До речі, знайти статті, в яких автори описували проблеми цієї моделі не так вже й просто, навіть в 2016 році. Але як ми всі знаємо, срібної кулі немає, а, значить, і в цій моделі все добре далеко не для всіх.
Що не так з класичним GitFlow?
Історія починається з того, що класичний GitFlow передбачає велику кількість merge-комітів. Причому проблема не в самих merge-коммитах (які, як ви далі побачите, все одно будуть присутні в історії), а в їх величезній кількості. Дебати на тему «Merge vs Rebase» часто зустрічаються на просторах інтернету (пошукові системи підкажуть). У Atlassian, до речі, є хороша стаття, в якій описується різниця цих двох підходів. Так у чому ж справа?
  1. Історія комітів стає просто жахливою. На фото нижче день роботи команди.

    Git Flow History

    Так, у нас є
    git log --first-parent
    та інші можливості відфільтрувати дерево, але це несильно допомагає повноцінного аналізу історії. Якщо ж у команди розробників, крім класичного GitFlow, немає ніяких інших угод по веденню Gitрепозиторію, то в цій історії можна буде цілими пачками спостерігати коміти c абсолютно безглуздими повідомленнями "fix", "refactoring", "", і т. д. Це зробить історію комітів практично непридатною навіть для самого поверхневого аналізу.
  2. Якщо ваш релізний скоуп змінюється (а в Agile це буває рідко), то класичний GitFlow вам навряд чи підійде. Якщо у вашому робочому процесі часто зустрічаються фрази, які потрапляють під шаблон "Замовнику терміново потрібна збірка, в якій [\w]*", то з історією комітів, наочно представленій у попередньому пункті, ваше життя перетвориться на суцільне пекло. Я не жартую.
  3. merge-комітів ускладнюється використання
    git bisect
А що хотілося б?
Дуже складно пояснити, чому так важливо, щоб історія комітів була чистою. Досвідченим розробникам не потрібно пояснення, чому чистим повинен бути вихідний код, для них це твердження — аксіома. На мій погляд аналогія тут абсолютно пряма. Також як і кожна строчка чистого коду, кожен комміт історії повинен бути на своєму місці і зрозумілий кожному, навіть сторонньому, розробнику. Так, брудний код теж може бути робочим, але на скільки зручно з ним працювати? Як швидко вдасться розібратися нового співробітника? Те ж саме і з історією комітів. Навіть брудна історія буде знати абсолютно все про всі зміни в проекті, але чи буде зручно з нею працювати?
Для того щоб робота з Git-репозиторієм була простою, зручною та зрозумілою, на мій погляд потрібні всього дві речі:
  • Лінійність історії змін. Це властивість обмежує товщину дерева комітів константою, роблячи його максимально простим і наочним для аналізу.
  • Логічна завершеність кожного коміта. Це властивість сильно збільшує гнучкість історії змін. У цьому випадку, якщо буде потрібно, окремі доробки можуть бути без зайвих складнощів перенесені з допомогою команди
    git cherry-pick
    . Або повністю скасовані за допомогою команди
    git revert
    , яка у випадку простого коміта набагато простіше, ніж у випадку merge-коміта.
Якщо обидва властивості виконуються, дерево комітів буде виглядати наступним чином:
Rebase Flow History
Як цього досягти?
Треба зовсім не багато підредагувати класичний GitFlow. При цьому робота з develop, master, release і hotfix бранчами залишається рівно такий же, як і в класичному GitFlow. Правки ж стосуватимуться виключно роботи з feature-бранчами.
  1. Перед вливанням feature-бранчу в підсумковий, йому необхідно зробити інтерактивний rebase командою
    git rebase -i develop
    , при цьому всі проміжні коміти в бранчі злити (squash'ить один. Бувають випадки, коли історію комітів feature-бранчі має сенс залишити, але ці випадки на практиці дуже рідкісні. При гарній декомпозиції задач кожна невелика задача являє собою атомарний і логічно завершене зміна системи, яка відмінно укладається в одному коммите. Враховуючи, що всі зміни в рамках завдання можна з'єднати в один комміт в самий останній момент, під час роботи над завданням розробник може безперешкодно створювати безліч проміжних комітів, необхідних йому для потенційного відкату. Ну і не зайвим буде додати, що є відмінна команда rerere, допомагає розробникам, часто виконують операцію rebase.
  2. Заливати feature-бранч у віддалений репозиторій необхідно за допомогою команди
    git push --force
    , так як в попередньому пункті ми виробили rebase-бранчу.
  3. Вливати feature-бранч в підсумковий необхідно командою
    git merge --ff-only feature
    , так як тільки в цьому випадку вдасться зберегти лінійність історії комітів і уникнути появи merge-коміта.
Як бачите, змін по роботі з репозиторієм зовсім не багато. І, підбиваючи певний підсумок цій частині статті, хочу поділитися посиланням на відмінну статтю, де також розглядаються плюси і мінуси класичного GitFlow і Rebase Flow.
Підтримка Rebase Flow в менеджерах репозиторіїв
Як я вже згадував на початку статті, підтримка класичного GitFlow є у безлічі інструментів, у тому числі і в різних менеджерів репозиторіїв. Тому далі я розгляну питання про те, як зараз йдуть справи з підтримкою Rebase Flow популярних менеджерів репозиторіїв. При цьому моя оцінка буде у форматі звичайної університетської позначки.
GitHub
Підтримка Rebase Flow: ДОБРЕ
насправді, у GitHub є практично все що потрібно. У налаштуваннях репозиторію є галочка «Allow squash merging».
GitHubSettings
Вона дозволяє при мерже pull request'а вибрати відповідний пункт і відредагувати підсумкове повідомлення до коммиту
GitHubMerge
В результаті pull request буде смержен лінійно і все коміти будуть схлопнуты в один.
Єдиний мінус, який я бачу на стороні GitHub, це
  1. відсутність можливості смержить pull request без злиття комітів. Дуже рідко, але це все-таки потрібно і, у випадку з GitHub, цей мерж доведеться виконати вручну.
Все вищесказане відноситься і до GitHub Enterprise, який може бути розгорнутий на серверах вашої компанії.
BitBucket
Підтримка Rebase Flow: НЕЗАДОВІЛЬНО
А за фактом її просто немає. Якщо ви хочете використовувати у своїй роботі Rebase Flow, то BitBucket в цьому вам ніяк не допоможе, все доведеться робити самостійно.
І це дивно, враховуючи що за текстом цієї статті я не раз посилався на відмінні статті з сайту Atlassian. Будемо сподіватися, що в майбутньому ситуація з підтримкою Rebase Flow зміниться, тим більше, що завдання на це вже давно заведено
Давайте тепер подивимося, що з підтримкою Rebase Flow у платного продукту від Atlassian.
Atlassian BitBucket Server (a.k.a. Atlassian Stash)
Підтримка Rebase Flow: ЗАДОВІЛЬНО
Я розглядаю BitBucket v4.5.2 і, можливо, в майбутніх версіях ситуація зміниться в кращу сторону. Зараз же з підтримкою в BitBucket Server дещо краще, ніж у його хмарному брата. Якщо у вас є доступ до адміністраторів, то ви можете їх люб'язно попросити у файлі
bitbucket.properties
змінити для вашого проекту/репозиторію налаштування мержа pull request'ів (документация)
  • plugin.bitbucket-git.pullrequest.merge.strategy.KEY.slug
    — налаштування для конкретного репозиторію
    slug
    проект
    KEY
    .
  • plugin.bitbucket-git.pullrequest.merge.strategy.KEY
    — налаштування для конкретного проекту
    KEY
    .
  • plugin.bitbucket-git.pullrequest.merge.strategy
    — глобальне налаштування для всього BitBucket Server.
Значення параметрів можуть бути наступними
  • no-ff
    — ніякого fast forward. Це значення за замовчуванням.
  • ff
    — при можливості, буде виконаний fast forward мерж.
  • ff-only
    завжди fast forward мерж. Ви просто не зможете смержить pull request, якщо це не можна зробити лінійно.
  • squash
    — зливає всі коміти в один і не створює merge-коміта.
  • squash-ff-only
    — зливає всі коміти в один і не створює merge-коміта, але робить це лише в тому випадку, якщо можливий fast forward мерж.
Як ви бачите, налаштування досить гнучкі, але є дві проблеми
  1. Немає web-інтерфейсу налаштувань, а звернення до адміністраторів сильно ускладнює робочий процес.
  2. не Можна вибрати поведінка для конкретного pull request'а, мінімальної настроюється сутністю є репозиторій.
Як тільки ці дві проблеми будуть усунені, підтримку Rebase Flow у BitBucket можна буде оцінити на відмінно. А поки ...
GitLab
Підтримка Rebase Flow: ДОБРЕ
Оцінюючи підтримку на https://gitlab.com, ми, по суті, оцінюємо підтримку в продукті GitLab EE, на базі якого він реалізований. Що ж стосується підтримки Rebase Flow GitLab CE, то її там просто немає.
Для розуміння того, як саме організована підтримка Rebase Flow, погляньмо на налаштування проекту
GitLabProjectSettings
Як ви бачите, тут навіть є проміжний варіант полулинейной історії, коли merge-коміти залишаються, але можливість прийняти pull request з'являється тільки в тому випадку, якщо feature-бранч є лінійним продовженням. Якщо вибраний цей варіант з полулинейной історією або «Fast forward merge», у нас з'являється додаткова можливість управління pull request'ом. А саме з'являється кнопка «Rebase onto ...», що дозволяє зробити з feature-бранчу лінійне продовження історії.
GitLabProjectRebase
Після чого можна без проблем взяти pull request, який буде смержен без створення окремого merge-коміта.
GitLabProjectAccept
Більш докладний опис цієї функціональності можна подивитися в документації (раз, два). Незважаючи на те, що скріншоти в ній трохи застаріли, вона не втратила своєї актуальності. На цьому в принципі підтримка Rebase Flow закінчується. Те що вона взагалі є — це, звичайно, плюс, але в ній явно не вистачає
  1. Можливості обрати поведінку для конкретного pull request'а. Так, перед прийняттям pull request'а можна поміняти налаштування самого проекту, але це не дуже зручно.
  2. Можливості автоматичного злиття комітів feature-бранчу в один.
Що в підсумку?
Зараз більшість менеджерів Git-репозиторіїв реалізують підтримку Rebase Flow в будь-якому вигляді. І зручність роботи у них на порядок вище, ніж кілька років тому. Але все-таки, на мій погляд, мінуси поки є у всіх продуктів, і я продовжую вірити, що в майбутньому вони їх виправлять.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.