Git Rebase: хто він такий і в чому його сила

Привіт, я Ганна Ліхтман — Lead Software Engineer, фанатка чистого коду, чистої архітектури та, як слідство, чистої історії комітів. Я людина, яка не раз виглядала отак 🫠, коли відкривала Git history у чужому Merge Request.

За роки роботи я бачила багато — від «commit1», «commit2», «final-final-fixed», до «try again pls» і «now it should work for real». І повірте, нічого так не псує настрій, як ціла стрічка незрозумілих змін, особливо коли ти reviewer, а в тебе п’ять хвилин до стендапу.

Мене часто запитують:

«Навіщо той Rebase? У нас і так все працює».

І я щоразу усміхаюсь і думаю:

«Поки ти не натрапив на гілку зі 132 комітами, де п’ять із них — це ‘fixed typo’, ти просто не бачив справжнього болю».


У цій статті ми поговоримо про Git Rebase не як про страшний ритуал для обраних, а як про інструмент, який може врятувати ваш Git history від перетворення на хаос.

Тут ви дізнаєтесь:

  • Чи справді існують погані історії в Git — і як вони виглядають.
  • Навіщо нам потрібен Rebase, якщо «і так усе працює» (спойлер: не завжди).
  • Що таке інтерактивний Rebase — і чому це не страшно.
  • Як на практиці привести свої коміти до ладу, щоб рев’ювери не проклинали вас ночами.

Це не буде суха документація. Це буде щира, жива розмова про один із найпотужніших інструментів Git — з реальними прикладами, сценаріями з життя й порадами, які ви зможете використати вже завтра. Готові? Поїхали!

Не існує поганих історій... чи все ж є?

Ні, я зараз не про Git як систему — не про те, як його створив Лінус Торвальдс у пориві розчарування, і не про легендарні апдейти 2005 року.

Я зараз про іншу історію — вашу Git-історію. Ту, що живе всередині кожної гілки вашого репозиторію. Ту, яка іноді лякає більше, ніж продакшн без моніторингу.

У типовому проєкті є кілька гілок:

  • main, develop, feature/awesome-new-thing
  • і звісно — наші улюблені hotfix/hotfix/fix-final-really-final-2

І все б нічого, але відкриваєш Git history — і там... Git-apocalypse.

Ти дивишся на ці коміти, і в тебе одне питання:

«А хто це писав? Я? Та ні... не може бути. Я ж нормальна людина».

І тут починається класика:

  • «Fixed something»
  • «Changed stuff»
  • «Refactored thing»
  • «Updated code again because why not»

І от з цим добром ти йдеш на code review.

😰 Коли приходить рев’ювер...

У GitLab є прекрасна фіча — перегляд комітів по одному. Ідея проста: кожен коміт має бути атомарним — маленьким, логічним і незалежним.

Тобто, можна читати твої зміни поетапно, ніби книгу з коротких розділів. Але що робити, коли в тебе:

  • 3 нормальні коміти;
  • 5 штук «Fixed after review»;
  • 17 «Updated something»;
  • 40 штук, які вже й сам не пам’ятаєш?

Reviewer починає перегляд, натискає стрілочку... ще одну... ще одну... І десь на десятому коміті розуміє, що логіки тут не більше, ніж у сюжеті останнього сезону «Гри престолів» (фанати, сорян...).

🧹 Що ж із цим робити?

Тут з’являється перша думка:

«А давайте все засквошимо! Одна галочка — і 112 комітів перетворюються на один. Перемога!»

Так, Squash у GitLab — це непоганий emergency-план. Але, зізнаємось, це не завжди елегантно. Бо в такому випадку зникає не тільки хаос — зникає і цінна історія. Навіть хороша.

Особливо якщо вона була... ну, бодай трохи структурована.

І ось тут варто згадати про випадки, коли нам навпаки потрібні атомарні коміти. Уявімо: ви створюєте login modal form.

Що ви зробите? Правильно — дрібні логічні кроки:

  • feat(kit): create button
  • feat(kit): create input
  • feat(kit): create modal
  • feat(login): create login form — де ви зібрали всі попередні елементи.

Це виглядає чисто, передбачувано, і що важливо — гнучко. Бо якщо завтра продакт скаже «Мені ця кнопка не подобається — прибери її», вам не треба розгрібати монолітний commit з тисячами рядків. Ви просто видаляєте окремий atomic commit або робите revert.

Але... Потім на сцену виходить рев’ювер із коментарем:

«А можна border radius модалки зробити ще трішки більш округлим, бо ці кути різали мені душу».

І ви такі:

  • fix(kit): update modal border-radius
  • fix(kit): fix of modal border
  • fix(kit): final fix
  • fix(kit): actually final
  • fix(kit): one more time i promise

І ось у вас уже 10 комітів, половина з яких — просто патчі, що забруднюють історію.
Ви починаєте шукати варіанти:

  • Сквошити все? Можна, але втратите сенс і гнучкість.
  • Залишити як є? (спойлер: Reviewer втратить віру в людство)
  • Створити ще один commit on top? А далі ще один? І ще?..

А може, варто зробити Rebase?

💡 Ось тут на сцену і виходить справжній головний герой цієї історії — Git Rebase: той, хто допоможе вам прибрати шум, залишивши зміст.

Готові дізнатись, як це працює і чому це не страшно? Погнали.

🔁 Що таке Git Rebase і навіщо він потрібен?

Якщо Git — це історія змін у коді, то Rebase — це сама машина часу. Ви не просто повертаєтесь у минуле. Ви можете переписати його.

Кожен коміт у Git — це нода, а HEAD — це та мітка, де ви зараз перебуваєте. Зазвичай ми працюємо собі на останньому коміті в гілці — і все ок.

Але з Rebase ми можемо:

  • перемістити коміти в інше місце в історії;
  • «перепригнути» на master чи інший бранч;
  • і навіть повністю переписати послідовність комітів, наче це чернетка в Google Docs.

Це не просто мікроманіпуляція над історією — це спосіб зробити її лінійною, чистою і читабельною. Бо, як кажуть: «Чистий код — це добре. А чиста історія комітів — ще краще».

🧭 Навіщо взагалі цей Rebase?

Подивімося на реальну ситуацію.

У вас є master (червоний), і з нього створено гілку first (синій). Ви працюєте над фічею, все чудово. Але master живе своїм життям: інші команди пушать, створюють баги (хе-хе), фіксять баги, додають апдейти.

І ось настає момент істини: потрібно підтягнути master у свій бранч. Що робити?

Варіант 1: Merge

Ми просто робимо git merge master, і...
Git створює додатковий коміт Merge master into first.

Стає більше вузлів. З’являється «гребінка». І якщо ви це робите щотижня, а фіча тягнеться кілька тижнів — гілка перетворюється на спагеті з мітками Merge, Merge, Merge...

Варіант 2: Rebase

Замість того, щоб створювати нові вузли, Rebase бере ваші коміти — і переписує їх так, ніби ви від самого початку почали роботу від найновішого master (! меджик).

🤹‍♀️ Rebase — це не про «магію», а про контроль

  • Ви зберігаєте лінійну історію.
  • Відкат змін — легкий і безпечний.
  • Reviewer бачить чітку послідовність логічних комітів.
  • Git Blame працює краще.
  • А історія читається, як технічна новела.

І знаєте що? Навіть SOLID про це говорить.

S — Single Responsibility Principle.

І якщо вже кожен клас має відповідати тільки за свою відповідальність, то нехай і кожен коміт відповідає за конкретну зміну, а не за «ну ми тут все злили в master — дивіться самі».

Наступним кроком ми глянемо, як Rebase стає ще потужнішим, якщо зробити його інтерактивним. Там і squash, і reorder, і rename — там усе в наших руках (му-ха-ха-ха!).

👉 Готові? Пірнаємо в інтерактивний Rebase далі.

🎮 Додаємо інтерактивності

Окей, ми вже знаємо, що Rebase — це круто. Але інтерактивний Rebase — це вже рівень богів, де можна:

  • перейменовувати коміти;
  • міняти їх місцями;
  • об’єднувати, викидати, редагувати;
  • і навіть виконувати команди між ними.

Звучить як чаклунство (поза межами Хогвартсу), правда?

Як його запускати?

Дуже просто:

git rebase -i HEAD~N

або

git rebase --interactive HEAD~N

Де N — кількість останніх комітів, з якими ми хочемо попрацювати.
Уявіть, що ви кажете Git:

«Покажи мені останні N кроків — я подивлюсь, що з ними зробити».

Що нам дає цей режим?

Git відкриває перед нами список останніх комітів і пропонує набір команд.
І тепер ми можемо:

  • pick — залишити як є;
  • reword — змінити назву коміту («refactor login logic» звучить краще, ніж «oops»);
  • edit — залізти в коміт, щось підправити й зберегти;
  • squash — об’єднати з попереднім комітом (і змінити повідомлення);
  • fixup — об’єднати з попереднім, але без зміни опису (Git мовчить, як ніндзя);
  • drop — викинути коміт геть («якщо тебе не було, то й не треба»).

Все це допомагає нам навести порядок у власній гілці, або навіть у тій, що походить з master.

А що ще є в інтерактивному режимі?

Git пропонує ще кілька команд для глибшої роботи з історією:

exec — виконає shell-команду після конкретного коміту. Наприклад, запустити тести, скрипт, чи навіть щось божевільне типу say «Commit is done!» (на свій страх і ризик).
break — зупинить Rebase на цьому кроці. Можна використати як контрольну точку: «Отут я хочу зупинитись і подивитись, що відбувається».
label / reset label — маркує певні місця в історії. Особливо корисно, якщо ви розбиваєте великий Rebase на логічні блоки (наприклад, «Коміти для UI», «Коміти для API», тощо).
merge — ну тут все ясно, це Git, не Excel — воно зіллється, якщо попросити ввічливо 😌

Але є одне ЗОЛОТЕ правило:

Перед тим як робити Rebase, зробіть бекап.

Один раз забув — і ти вже не девелопер, а детектив, який намагається зрозуміти, куди зникли твої коміти, і чому git reflog виглядає як список рішень, про які ти шкодуєш.

Тому:

git branch backup-before-rebase

Це ваша «кнопка ПАНІКА».

А ще — не соромтесь git rebase —abort або git reflog — вони існують, щоб рятувати.
І пам’ятайте: всі помиляються, але тільки найсильніші роблять бекап перед тим, як почати магію.

Далі переходимо до практики — покажемо все це в дії: як саме застосувати інтерактивний Rebase, що відбувається при squash, як змінити коміт, і коли це все реально працює краще, ніж здається.

🛠 Рухаємось до практики

Пам’ятаєте нашу задачу з самого початку — створення login модалки?

Тепер уявімо, що до цієї акуратної структури почали додаватись фікси, хотфікси, хотфікси до фіксів, «майже фінальні зміни» — і виглядати це почало отак:

О ні. Вийшла класика: «фічу робили три дні, фіксили — три тижні». А ми ж хочемо зберегти історію чистою, а не перетворити її на архів хаосу.

Тож, настав час зайти в історію з редакторським скальпелем — і використати Git Rebase, щоб все упорядкувати красиво.

Перший крок: визначити діапазон

Куди нам перемістити наш HEAD?

Ми хочемо пройтись по кількох останніх комітах — для цього використовуємо:

git rebase -i HEAD~N

де N — кількість комітів, з якими хочемо працювати.

В ідеалі ми такі: HEAD~16, бо думаємо: «Та в мене там напевно штук 16...»
А Git такий:

fatal: invalid upstream ’HEAD~16′

Окей, чесно — не вгадаємо. Тому викликаємо нашого найкращого помічника:

git log --graph --decorate --pretty=oneline --abbrev-commit

І він покаже нам все — красиво, зрозуміло, з кольоровими вузлами.

Виявляється, у нас лише 4 коміти — а ми вже хотіли мандрувати до Палеоліту 🙃

Запускаємо Rebase

Окей, запускаємо:

git rebase -i HEAD~4

Git відкриє список із наших чотирьох комітів у редакторі:

А тепер пояснимо, що значить pick і edit:

  • pick — беремо коміт як є. Нічого не міняємо. Просто приймаємо.
    Це як натиснути «Оформити замовлення» без змін до кошика.
  • edit — зупиняємось на цьому коміті, залізаємо всередину, змінюємо щось у коді, додаємо, видаляємо — і «зшиваємо» назад. Ця опція — як сказати офіціанту: «Я зараз сам на кухню, хочу трохи приправити».

✂️ Наш кейс: редагуємо border radius у модалці

Ми знаходимось на останньому коміті, але хочемо змінити border-radius, який був зроблений ще у create modal.

Міняємо pick на edit (або просто e) навпроти потрібного коміту:

Далі ми натискаємо Ctrl+С і внизу пишеться згадка, що робити, щоби просто вийти з Vim:

Але ми пишемо :wq — це означає, що ми вийдемо та збережемо все, що ми наробили. Бачимо, що зупинилися на create modal:

Тепер Git «зупиняє час» — ми переносимось у минуле, прямо в той коміт. Комітів, які були після — більше не існує (поки що).

Бо це все було в наступних комітах, ми перемістились в історії. І тут навіть Git нам підказує, що ми можемо використати amend після того, як все зробимо й будемо задоволені змінами:

Тож нам треба було змінити border radius. Змінюємо з 6 на 8, і бачимо, що в нас зʼявився коміт, що ми зробили якусь зміну:

Після цього в терміналі:

git add .

git commit --amend

--amend не створює новий коміт, а додає зміни до поточного.

Так, ніби ви відредагували вже надіслане повідомлення, і ніхто не помітив. Git ще дасть вам можливість оновити опис коміту — або залишити все як є.

Amend бере всі зміни, які ви зробили й додали через git add, і чіпляє їх до того HEAD, до того коміту, де ми зараз знаходимось. При цьому воно не створює новий коміт. Git нас запитає, чи дійсно ми збираємось робити цей коміт (ось такий він турботливий).

Ми підтверджуємо, натискаємо Ctrl+С, :wq і маємо підтвердження наших змін.

Ще раз повторимо те саме, але якщо нас попросять змінити назву кнопки.
Переходимо по інтерактивному ребейзу edit до кнопки:

Нам знову підкажуть, що ми зупинилися на Button:

І в коміті пропаде наша остання модалочка. Ми переходимо в Button і бачимо, що цей компонент у нас більш продуманий, готовий, але якби тут був інший Title — ми б його змінили. В нашому випадку можемо, знову ж таки, змінити border radius:

Знову прописуємо git commit --amend , підтверджуємо зміни. Готово, ми молодці!

🌀 Друга задача: а змініть це знову...

І тут ви ще не встигли допити каву, як приходить новий запит:

«Слухай, а все ж таки давай border-radius зробимо знову 6px?»

Знайомо? Таких «передумали» в проєктах більше, ніж комітів із назвою final_final_last_fix_3.

Окей, ви відкриваєте Modal, міняєте значення з 8 назад на 6...

І тільки потім усвідомлюєте: «А наш HEAD зараз не там, де треба».

Що пішло не так?

Замість того, щоб зробити rebase і зупинитись на потрібному коміті (наприклад, create modal), ви просто внесли зміни в останній — LoginForm.

І все... Тепер ці правки приклеїлись до не того місця.

Якби це були лише пару пікселів — можна просто натиснути Ctrl+Z, махнути рукою і зробити все по новій.

Але в реальних задачах це може бути:

  • багатогодинна правка стилів;
  • складна бізнес-логіка;
  • або... hotfix в проді (так, і таке буває).

Варіант порятунку #1: git stash

Можна сховати зміни ось так:

git stash

Це як скласти речі в коробку, позначити «не викидати!» і відкласти. Потім:

  1. робимо rebase на потрібний коміт;
  2. і дістаємо зміни:

git stash pop

І вуаля — зміни застосовані вже до того коміту, куди й треба.

Варіант порятунку #2: fixup + autosquash

Але ми підемо цікавішим шляхом. Трошки розумнішим. Трошки чарівним.

Спершу — дивимось на хеш коміту create modal, щоб прив’язатись саме до нього:

git log --graph --decorate --pretty=oneline --abbrev-commit

Нехай потрібний коміт має хеш 3b95ef3.

Додаємо fixup-коміт

Ми вже зробили зміну (повернули radius до 6), і тепер:

git add .

git commit --fixup=amend:3b95ef3

🔍 Цей фокус створює новий коміт, який прив’язується до існуючого і каже:

«Я — поправка до коміту 3b95ef3, приклей мене туди, будь ласка».

Звичайний git rebase -i HEAD~5 покаже вам окремий fixup-коміт.

Але ми хочемо, щоби Git сам зробив squash і приклеїв його без зайвих рухів. Тому додаємо прапорець —autosquash:

git rebase -i --autosquash HEAD~5

Тепер fixup акуратно перемістився туди, куди треба — прямо під коміт модалки, і вже з командою fixup, а не pick.

Вам лишається лише зберегти (:wq), і все злилось красиво.

Перевірка

Знову перевіряємо історію:

git log --graph --decorate --pretty=oneline --abbrev-commit

І бачимо: все чисто, красиво, комітів знову 4 — а не 5 з лишком. Mission complete.

💡 Порада: якщо знаєте, що будете часто робити fixup, можете одразу запускати інтерактивний Rebase з —autosquash. Воно просто працює.

Третя задача: наводимо фінальний блиск — drop і reword

Ну що, ми вже:

  • редагували коміти через edit;
  • допилювали їх через amend;
  • навіть влаштували autosquash із fixup.

Тепер час навести остаточний порядок і відкинути зайве, залишивши лише найкраще. А саме — потренуємось із drop і reword.

Сценарій: компонент іконки

Маємо окрему гілку для IconComponent.

Усе було б добре, але поки ми працювали, хтось уже влив цілу колекцію іконок у master.

Тепер наша одна скромна іконка не просто непотрібна — вона може викликати конфлікт при злитті. Тож ми вирішуємо: видалити її коміт, але при цьому залишити створений компонент.

Ми як завжди запускаємо наш інтерактивний Rebase:

git rebase -i HEAD~2

Бачимо, що один із комітів — це додавання іконки у public. Саме його нам і треба прибрати.

Замість pick пишемо:

drop 1feaf78 feat(public): add check icon

або коротше:

d 1feaf78 feat(public): add check icon

Зберігаємось (:wq) — і... все!

Бувай, коміте. Тебе тут ніколи й не було 😌

Перейменовуємо коміт — команда reword

Тепер наш єдиний коміт звучить скромно: feat(kit): create icon component. Але ми, як відповідальні розробники, згадуємо:

«Ой, ми ж забули вказати номер таски!»

Знову запускаємо:

git rebase -i HEAD~1

І змінюємо команду з pick на:

reword ba2f44d feat(kit): create icon component

або просто:

r ba2f44d feat(kit): create icon component

Зберігаємось (:wq), і Git каже:

«Окей, друже, а тепер скажи, як це має називатись?»

Ми додаємо таску в кінець:

feat(kit): create icon component — TASK-195

Знову :wq, Git задоволений. І ми — теж 🙌

Ми навчилися не просто натискати на кнопки, а редагувати, переписувати й чистити Git-історію так, ніби ми сценаристи власного коду.

Тепер, коли хтось скаже «там трохи брудна історія» — ви не просто зрозумієте, що саме брудне, а ще й знатимете, як це виправити красиво.

Висновок: Git Rebase — це не страшно, це мистецтво

Окей, ми з вами пройшли повний шлях.

Від моменту, коли Git-історія виглядає як хаос після дедлайну — до стану, коли кожен коміт виглядає як акуратна цеглинка в стіні архітектури. Ми:

  • розібрались, чому «погана історія» — це реально проблема, а не вигадка перфекціоністів;
  • навчилися edit-ити, squash-ити, fixup-ити, reword-ити і навіть drop-ати, коли треба;
  • врятували себе від незручних комітів типу fix_fix_last_final2;
  • і на завершення — перетворили хаос у чітку, логічну розповідь, яку не соромно показати на code review.

А головне — ми перестали боятись Rebase, і навіть почали трошечки... кайфувати від нього ✨

☕ То для чого це все?

  • Щоб вас поважали не лише за чистий код, а й за чисту історію.
  • Щоб ваші pull request-и читались легко.
  • Щоб ваш reviewer не плакав в подушку, гортаючи 113 неясних комітів.
  • Щоб, коли хтось скаже: «а можна змінити щось у середині?», — ви відповіли:

«Звісно. Зараз зробимо git rebase -i — і все буде красиво».

🔥 Наостанок:

  • Робити Rebase — не страшно. Не робити бекапи перед ним — страшно.
  • Git — це інструмент. Але у ваших руках він стає інструментом контролю, а не джерелом стресу.
  • І пам’ятайте: чиста історія — як хороший стиль в одязі. Начебто дрібниця, але помічають усі.

Тож вперед — не просто кодуйте, творіть історію, яку приємно читати.

Більше інформації про Git Rebase — у моєму вебінарі.

До нових HEADів, друзі 🫶
І нехай --autosquash завжди буде з вами.

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось38
До обраногоВ обраному24
LinkedIn

59 коментарів

Підписатись на коментаріВідписатись від коментарів Коментарі можуть залишати тільки користувачі з підтвердженими акаунтами.

Ніби й хороша стаття з гіт-ребейзу, з хорошими прикладами, але їй бракує найголовнішого:
1) Де розділ про недоліки використання ребейзу?
2) Де розділ про недопустимість використання ребейзу?
3) Чому про force-push ані слова?

Я сам дуже люблю ребейз і використовую його для своїх локальних гілок, ще не запушених на сервер, поки триває розробка якоїсь немаленької фічі. Але, відверто, сквош-мердж з роками мені подобається все більше. І джунам пояснити набагато легше, і мороки набагато менше, і проблем набагато менше. Тому ребейз — це як бібоп-джаз (точно не для всіх і не для всіх сценаріїв).

сквош-мердж з роками мені подобається все більше.

я почав зацінюват стиль як то «відкрив приватний бранч накидав в нього потрібні зміни у тому числі «начеріпікані» усе перевірив поправив проблеми і зробив сквош куда надо попутно ще раз перед самим комітом переглянувши зміни які самі йдуть у коміт сквош

меня бесит что постоянно надо ребейзится перед мержем. и если не дай боже девелопмент достаточно активный, то твой мр крайне редко заходит с первого раза
добавить сюда что тот же гитлаб, к примеру, не всегда способен поребейзить у себя и требует локального ребейза — это по настоящему бесит

меня бесит что постоянно надо ребейзится перед мержем.

Это уже вопрос политики репы. Обычно такое не выставляют, ну кроме как на явный конфликт мержа.

Но если все начинают сваливать свои правки на последний день перед форком релизной ветки — ну, тады ой.

добавить сюда что тот же гитлаб, к примеру, не всегда способен поребейзить у себя и требует локального ребейза — это по настоящему бесит

А локальный в таком случае проходит без жалоб на конфликт?

А локальный в таком случае проходит без жалоб на конфликт?

Да, локальный проходит без проблем и вопросов

Но если все начинают сваливать свои правки на последний день перед форком релизной ветки — ну, тады ой.

Нит, просто ревьювер проревьювил мр, поставил их на билд и мерж, первый зашел — остальные в очереди надо ребейзить.
и так с каждым.

просто [...]первый зашел — остальные в очереди надо ребейзить.
и так с каждым.

Нет, не «просто». Это локальная политика. У меня сейчас в gitlab есть проекты и там такого нет. Если кто-то так настроил, то по своим причинам. Если не устраивает, надо разбираться и обсуждать.

Да, локальный проходит без проблем и вопросов

Хм, вот тут не видел. Может, у него настроена повышенная критичность к возможным конфликтам.

Але, відверто, сквош-мердж з роками мені подобається все більше. І джунам пояснити набагато легше, і мороки набагато менше, і проблем набагато менше.

Поки не повертаєтесь через рік-два у пошуках, що ж це було і чому.

Я от прямо зараз розбираю гілку, яку майже рік не торкались, треба актуалізувати. В поточному стані це ≈60 комітів. Поки що зрозуміло, що там діється. Якщо б це засквошили — єдиним варіантом було б розібрати, що міняли, і переписати під таке ж ТЗ з нуля.

Тому тих, хто сквошить суттєво різні зміни в один коміт, я б відстрелював ще на підході.

Тому ребейз — це як бібоп-джаз (точно не для всіх і не для всіх сценаріїв).

Але для більшости таки підходить.

А якщо джуни щось не розуміють — вчити, поки не зрозуміють.

Якщо б це засквошили — єдиним варіантом було б розібрати, що міняли, і переписати під таке ж ТЗ з нуля.

це тому що сквош як і власне commit item має мати розумний розмір

хто сквошить суттєво різні зміни в один коміт

так для початку а чого вони вообщє потрапили у ту задачу до якої відносився той сквош?

ЗЫ: тобто щось там як то «написати відповідь на оцей комент на доу» і тут раз х.к простіті у туди в задачу потрапляє ще ну я там знаю 4 липня )) ну і ідуть вони разними комітами понятно но тепер да тепер ок можна всяку х.ню нести до коміта якщо разними комітами )) чи як се має бути на твій ідею?

так для початку а чого вони вообщє потрапили у ту задачу до якої відносився той сквош?

«Опять двадцать пять за рыбу деньги»

Чому ні? Що забороняє при вирішенні одної задачі зробити, наприклад, видалення, пʼять рефакторінгів і додавання нового функціоналу? І кожний окремим комітом, щоб він чітко акуратно означав що зроблено і чому, і його можна було перевірити всіма засобами?

Чиясь дебільна релігія — мов, одна задача — один коміт? Так йшла ця релігія лісом і полем разом з її носіями.

чи як се має бути на твій ідею?

Пиши так, щоб твої слова можна було розпарсити. Те що зараз навіть не потік свідомости, а якісь уривки того потоку.

Пиши так, щоб твої слова можна було розпарсити. Те що зараз навіть не потік свідомости, а якісь уривки того потоку.

не можу )) медицина каже вже всьо

Що забороняє при вирішенні одної задачі зробити, наприклад

певно що заважає при вирішенні задачі винести додаткові задачі в окремі задачі вже виходячи з того що вони на стільки важливі та вагомі (за розміром коміту) щоб мати власний коміт з власним описом тощо

адже ці коміти ти сам хочеш бачити у загальному стрімі правильно? тож 1 коміт 1 задача буде рівне то саме як 1 задача 10 атомарних комітів на частини задачі які усі та сама задача

тож просто по історії комітів то є буде те саме

з тієї правда відмінності що саму задачу можна буде відтрекати як задачі у тій там джирі а от «1 задача 10 комітів» то кожен окремий коміт буде посилатися так само на одну й ту саму задачу

а чого б тоді і не робити його і 1 комітом? хіба сам коміт не має бути аж так прозорий щоб по коду вже було видно отут задача отут додали отут рефакторінг отут рибу заворачували?

І кожний окремим комітом, щоб він чітко акуратно означав що зроблено і чому, і його можна було перевірити всіма засобами?

загалом же ж так система з лінійної моделі комітів дещо застаріла і загалом мати бодай 2 рівні коміту було би цікаво але я думаю воно просто повернеться до оригінальної задачі як то «формувати красиву (і внятну) історію 2-го рівня коміта»

тож схоже вийде те на те і вийде

Чиясь дебільна релігія — мов, одна задача — один коміт? Так йшла ця релігія лісом і полем разом з її носіями.

ну так зрештою просто твої коміти ніхто не буде читати і зрештою ніхто не буде й приймати просто бізнес ))

І ще,

але їй бракує найголовнішого:

Якщо чогось бракує, можна обговорити в коментарях, для того вони і зроблені. Але чому ви вирішили, що це найголовніше?

2) Де розділ про недопустимість використання ребейзу?

У яких випадках і чому? Наведіть хоча б базовий приклад. Краще два.

3) Чому про force-push ані слова?

А як він повʼязаний з темою статті?

Але чому ви вирішили, що це найголовніше?

Та тому, що ребейз переписує історію комітів. Якщо той, хто ребейзить, цього не усвідомлює — то він чи його колеги потенційно матимуть багато проблем.

У яких випадках і чому? Наведіть хоча б базовий приклад. Краще два.

Приклад 0 (сподіваюсь, її ніхто ніколи не ребейзить, бо це кримінал): Main-бранча
Приклад 1: CI-бранча (дев-бранча).
Приклад 2: Будь-яка спільна бранча, з якою тимчасово працює 2 і більше девів
Чому? Див. першу відповідь.

А як він повʼязаний з темою статті?

Повʼязаний безпосередньо, оскільки знову ж таки див. першу відповідь. При переписуванні історії бранчі запушити її без force-push неможливо, простий push не канає.

Та тому, що ребейз переписує історію комітів. Якщо той, хто ребейзить, цього не усвідомлює — то він чи його колеги потенційно матимуть багато проблем.

Що історія переписується — ну так для того він взагалі і зроблений. Чи ви маєте на увазі дещо інше?

Приклад 2: Будь-яка спільна бранча, з якою тимчасово працює 2 і більше девів

В мані по rebase є ціла глава «Recovering from upstream rebase», з поясненнями, методами і коментарями. Там же пояснено, що це особливий варіант не для всіх.

Але допоміжні репи Linux через це проходять постійно, народ там готовий до такого.

При переписуванні історії бранчі запушити її без force-push неможливо, простий push не канає.

Ну я би вимагав push з force-with-lease, а не просто force. У мене для нього є аліас («psfl»).
Але згоден, тут мало б продовжити статтю ще другою частиною.

Установить нормальные правила именований коммитов и бранчей и нагнуть девопсов на настройку серваков проекта чтоб не пропускать автоматически репу всякие абы как подписанные коммиты — вот залог порядка на проекте.
Я лично ребейзом пользусь только чтоб актуалитзировать фичебранч перед мержем — реально аккуратней выходит.
По поводу сквошей — узнайте у своего девопса политику push —force в компании, если бранч не заливали то не страшно, но переписывать историю пропушеного бранча может быть чревато.

Краще — ворог хорошого

Певен, що є ситуації, в яких це буде корисно, але на реальній практиці, зручніше ревьюіти одразу весь PR/MR цілком, а не кожен комміт окремо. При правильно побудованих процесах подібні реквести не мають містити тисячі строк змін, а отже і кількість/послідовність коммітів не має бути надто великою або хаотичною. Але всеодно дякую вам за статтю

«Правильні» процеси можуть бути різні.
Почитайте LKML. Там норма що є, наприклад, 10 комітів версії 2. Отримують фідбек. Через тиждень видають 10 комітів версії 3, змінені майже всі. Або 12 комітів, бо щось додано. Або навпаки якийсь видалений. А частина змін переїхала між комітами.
Це правильний процес чи ні?

Або таке. Тут ланцюг на 6 комітів. Там буває і більше. І у одного з комітів 11а ревізія. Це правильний процес чи ні? А на ньому розробляють Android. Мабуть, його майнтейнери щось розуміють?

В цілому дуже гарна стаття. Для полірування до ідеалу, окремі зауваження:

> Замість того, щоб створювати нові вузли, Rebase бере ваші коміти — і переписує їх так, ніби ви від самого початку почали роботу від найновішого master (! меджик).

Не було сказано, але треба завжди розуміти: хоч rebase і перерозташовує коміти після бази, але по тому, як воно їх перенакладає, це теж merge. Розуміння цього необхідне, щоб потім не страждати від розчарувань, і мати уяву, що робити при конфліктах.

Хоча б декілька слів, як робити локальний мерж при конфлікті. Я б для себе хотів більше гарних прикладів, які є автоматизовані засоби для цього, їх переваги і недоліки. Сам звик до простого vim тут, але іноді це дає забагато ручної роботи.

І до речі, якщо у вас не виставлено merge.conflictstyle = diff3 в глобальних налаштуваннях, то ви сам собі ворог. (Воно діє і на конфлікти при rebase і stash pop.)

> git rebase -i HEAD~N

Чомусь не вказан один дуже простий варіант, наприклад: git rebase -i main (чи як там зватиметься гілка, у яку треба потім додати). Зрозуміло, після того, як реально базуєтесь на ній (на тій версії, що прийнята зараз локально).

В списку дій для interactive треба додати більш деталей для ’break’ (’b’), який можна ставити в довільному місці. Це гарно на випадок, наприклад, розщеплення існуючого коміта на два. Тоді ставите перед тим, що розщеплювати, через git restore приймаєте зміни, комітите потрібну частину, інше видаляєте і робите continue.

Не вказано, що git status показує, чи знаходимось ми в rebase, і де саме. IDE можуть це теж показувати.

Не бачу звʼязку з Clean Code від Мартіна. Чиста історія — гарно. Самопротирічна оманлива маячня від Мартіна — ні. Краще концептуально базуватись на GRASP.

Autosquash... хм, ніколи не використовував, тому що завжди краще спочатку переставити коміти як треба (і розвʼязати всі конфлікти), перевірити коректність результату і потім явно сказати squash або fixup на потрібних комітах.

Іноді трапляється таке, що навіть git rebase —abort не виконується. Тоді треба видалити весь ${WRKDIR}/.git/rebase-merge/ (або відредагувати, якщо розумієте, що робите) і через git reset повернутись у попередній стан.

> У GitLab є прекрасна фіча — перегляд комітів по одному.

У нього це слабо зроблено. Найкраща реалізація у Gerrit. Але він не має вбудованих CI, трекера і wiki, тому його рідко зустрінеш в невеличких організаціях.

Звісно, можна було б хотіти більше деталей. Але як для першої частини, повторюсь, вже більш ніж добре:))

Гарна стаття. Але я з деякими моментами не згоден. Для прикладу:

Що ви зробите? Правильно — дрібні логічні кроки:

feat(kit): create button
feat(kit): create input
feat(kit): create modal
feat(login): create login form — де ви зібрали всі попередні елементи.

Для мене це вже виглядає як чотири пулл реквести, які пройшли (кожен окремо) ревʼю і були змерджені з використанням скваша.

В такому випадку кожен ПР може мати скільки завгодно комітів, буде меньший за обсягом (а відповідно легше його продивитись).

І тоді у вас не постає таке питання:

Ви починаєте шукати варіанти:

Сквошити все? Можна, але втратите сенс і гнучкість.

Так, звісно сквошити.

В такому випадку кожен ПР може мати скільки завгодно комітів, буде меньший за обсягом (а відповідно легше його продивитись).

там уже є спеціальна форма pool request яка включає сам коміти чи якось так тобто придатна до код ревью не як шмат коду на +100500 а саме як історія

... потім знайду як називається

Для мене це вже виглядає як чотири пулл реквести, які пройшли (кожен окремо) ревʼю і були змерджені з використанням скваша.

В кожній морді (GitHub, Gitlab, Bitbucket, Gerrit, etc.) свої поняття. В Gitlab, Gerrit можна дивитись їх окремо (в Gerrit зручніше, в Gitlab так собі) і ревʼюїти окремо.

Так, звісно сквошити.

За сквош суттєво різних по суті коммітів — позбавляти зарплати за місяць, за повторення — звільняти. Тут я згоден з автором статті.

я також люблю rebase тільки так і працюю але дочитав до «feat(kit): create button» і зрозумів що ніяку чисту історію з таким підходом не отримати хоть ти напиши цілу книгу а не статтю. Навіщо ревьюверу бачити 10 комітів Джуна який тупо не знає що робить? Або інший кейс, наприклад роблю велику фічу і сьогодні воно типу так треба робити а у останній день виявляється якийсь нюанс і місцями код стає нерелевантним, навіщо ревьюверу бачити те що по суті перероблено?

Навіщо ревьюверу бачити 10 комітів Джуна який тупо не знає що робить?

Ну не робіть ревʼю, хай сміття іде в продуктин.

а у останній день виявляється якийсь нюанс і місцями код стає нерелевантним, навіщо ревьюверу бачити те що по суті перероблено?

Ну а він і не побачить. Побачить нову версію, де перероблено як треба. Що не так?

Так он эти 10 коммитов и не будет видеть — ревью лист по diff-у генерится между бранчами. Коммиты там можно посмотреть по желанию.

Ніколи не юзав і не розумію нафіга він і для кого, коли є squash коміти при мерджі. Коміт — номер тікета. Шо ще треба а головне — нафіга?

Тому що робити рев’ю десяти маленьких комітів простіше, ніж одного великого. Плюс простіше помилитися.

навіщо робити ревью комітів? О_О
ви робите ревью пул реквестів. (Чи не робите?)
А якщо треба глянути що змінілось після фіксу комментів — дивишся комміт.

Я дивлюся рев’ю пулреквеста по комітам від початку до кінця.
Тоді хоч якось можна зрозуміти, що відбувається.
Якщо один коміт ±/ 1000 рядків, то перевірити ніяк.

йой, співчуваю. а навіщо? чому не глянути весь ПР? Бо в наступних коммітах ченжи, шо ви дивились — можуть змінітись і ви витратете час в нікуди.
Просто імхо якщо у вас ПРи по 10 000 рядків, то це більше про процесси, ніж про те як з гітом працювати

чому не глянути весь ПР?

Тому що багато змін важко зрозуміти. Мені треба буде стянути PR, розбити його правильно на коміти за допомогою rebase, перевірити кожний коміт, і тільки тоді я зможу зробити висновок щодо PR.

Знову таки, на етапі rebase у себе я знаходжу у себе багато помилок. Бо в атомарних комітах простіше бачити помилки. Для мене це просто питання культури розробки. Так, можна писати спагетті код з goto, інколи це навіть простіше, але ймовірність припустити помилку там буде більше.

Бо в наступних коммітах ченжи, шо ви дивились — змінілись.

Тому і треба rebase :-)

Бо в атомарних комітах простіше бачити помилки

я ж про це і кажу — якшо засквошити то і буде один атомарний коміт. і ребейз не потрібний

я дійсно взагалі не розумію чим допогмає ребейз. у мене у голові не мапиться потреба в коміітах по типу «fix code» " fix test" «refactor prev idea» «more changes»

я ж про це і кажу — якшо засквошити то і буде один атомарний коміт. і ребейз не потрібний

Атомарний означає неділимий. Тобто мінімальна семантична одиниця, яку не можна розділити на менші без втрати семантики.

Якщо засквошити, то буде один складний коміт, збірна солянка.

я дійсно взагалі не розумію чим допомагає ребейз

Ок, припустимо ми зробили змінили метод nа переіменували його. У цьому разі якщо це буде два окремих коміта, то я побачу в одному логіку, а в іншому переіменування. На переіменування у можу не звертати великої уваги, бо довіряю автору чи IDE. Тому я можу зосередитися лише на змінах у логіці.

Коли це один коміт, то виглядає як зміни в лозіці, а навколо насрано переіменування. Вже дивитися неприємно.

Будь який розподіл на коміти це декомпозиція логіки. Ти бачиш з чого складається PR.

Якщо засквошити, то буде один складний коміт, збірна солянка.

Так, і шо? Це ж чудово. Мейн сам по собі — збірна солянка з таких комітів які мають тікет нейм
Приклад таких комітів в мейне збірних солянок:
— PROJECT-1234: «Bug X fixed»
— PROJECT-2234: «Feature X»

Ось як має виглядати проект. Я не хочу в мейні бачити купу комітів, особливо тих, де хтось змівив назву функції. Це банально засирає гіт лог мейну непотрібом
який не відноситься до суті. Особливо буде круто виглядати git tag релізу з такого коміта по типу «rename»

Будь який розподіл на коміти це декомпозиція логіки. Ти бачиш з чого складається PR.

ні, не завжди, це ще рефакторінг, передумав шось, і таке інше. (нащо при цьому дивитись перший коміт, коли в останьому цього нема вже? не розумію)
10 комітів може ходити навколо однієї функції без декомпозиції логіки

Коли це один коміт, то виглядає як зміни в лозіці, а навколо насрано переіменування. Вже дивитися неприємно.

так а навіщо це взагалі дивитись??)) Ви ПР мерджете і ревьюваєте, а не комміти. Я розумію що саме ви рев’юваєте коміти, але людина робить ПР з фічею. І саме фіча тут головна суть, а не «як я прийшов до цієї фічи за 10 комітів»

Ок, припустимо ми зробили змінили метод nа переіменували його. У цьому разі якщо це буде два окремих коміта, то я побачу в одному логіку, а в іншому переіменування.

Ви серьезно в таких моментах робити окремий комміт на зміну назви в функції? Навіщо? Просто шоб красивий коміт був? Я знов не можу зрозуміти як це допоможе в контексте ревью Пул Реквеста
В мене наприклад і у всіх з ким я працював за 8 років, назва функції може змінитись у будь-якому коміті з купою інших ченжів. Але мене це не бентежить бо я ревьюваю Пулл Реквести (як і всі з ким я працював)

Ви ПР мерджете і ревьюваєте, а не комміти.

Ні, я можу робити рев’юв простих комітів. На складний ПР я просто чесно відповім, що зробити якісне рев’ю неможливо.

Більш практичний приклад, наприклад, такий. Була певна підсистема, код якої був розмазаний по усьому проекту, ще й накладений на архітектурні особливості різних плат. Потім було прийнято рішення використовувати новий тип плати, не сумісний з тими, що були. Виникло питання з цією підсистемою. Мій рефакторінг складався приблизно з 500 комітів. Але кожен з них було легко перевірити: тут додали аргумент, тут це код перенесли з одного файлу в інший, ... Таким чином при рев’ю можна було переконатися, що нічого не зламано.

Але мене це не бентежить бо я ревьюваю Пулл Реквести (як і всі з ким я працював)

Тут я не бачу сенсу в такому рев’ю, це карго-культ. Зазвичай логічні помилки помітити неможливо, тому таке рев’ю зазвичай чипляє оформлення: стиль кодування, там переорганізація у класи, ...

Якщо проект примітивний, що в принципі це може й працювати.

От, наприклад, приклад: PR до msquic, як ми бачимо, зміна версії, один рядок, окремий коміт.

Насправді, те що ви пишите виглядає, як недостатня декомпозиція задач і реалізації.
Якщо кожен з ваших комітів може бути атомарним, то в чому проблема виділяти їх в окремі ПР? Якщо вже дуже малі зміни, то можна групувати.

Для вашого прикладу: 500 комітів — і що хтось проходив по 500та комітах? не вірю. Звісно, що такий ПР ніхто не здатен проревʼювити.

Як називався ваш ПР в такому випадку — «Рефакторинг всього?»
Чому не розбити на домени: «Рефакторинг авторизації», «Рефакторинг тестів», «Рефакторинг ХХХ»

Якщо кожен з ваших комітів може бути атомарним, то в чому проблема виділяти їх в окремі ПР? Якщо вже дуже малі зміни, то можна групувати.

Іноді бувають адміністративні проблеми: хтось постановив що один тікет = один ПР, а наробити підтікетів це суперважна дія яка має затверджуватись менеджером 3-го рівня (який просто не розуміє, що таке коміт — йому треба план по валу). Ось тоді дійсно дупа.

Але якщо таких обмежень нема, і тулінг дозволяє, то краще робити декілька комітів на тікет — скільки треба, щоб кожний з них був акуратно зрозумілий і перевіряємий.

Якщо кожен з ваших комітів може бути атомарним, то в чому проблема виділяти їх в окремі ПР?

Можна, але що це дасть? Знову ж таки, невідомо що буде в результаті, а може це був хибний напрямок, а треба було робити по іншому? Так, і таке бувало, що приходилося дропати частину попередніх комітів та робити по іншому. Це робоіий процес.

Для вашого прикладу: 500 комітів — і що хтось проходив по 500та комітах? не вірю. Звісно, що такий ПР ніхто не здатен проревʼювити.

Так, звісно, я навіть відгук від нього отримав, що йому дуже сподобалося, і тепер він впевнений у змінах. І зайняло небагато часу.

Як називався ваш ПР в такому випадку — «Рефакторинг всього?»

Мені це як раз неважливо. Ок, припустимо називалося рефакторінг підсистеми QWERTY.

Чому не розбити на домени: «Рефакторинг авторизації», «Рефакторинг тестів», «Рефакторинг ХХХ»

Тому що це був рефакторінг лише однієї підсистеми в рамках одного модуля ядра. І там не було ні тестів, ні авторизації, лише код, пов’язаний з однією задачею.

Це банально засирає гіт лог мейну непотрібом
який не відноситься до суті. Особливо буде круто виглядати git tag релізу з такого коміта по типу «rename»

Ось про те і стаття, як зробити історію, щоб такого не було.

Ви ПР мерджете і ревьюваєте, а не комміти.

Назвіть вебморду, якою користуєтесь.

І я не розумію, як можна «ревʼюїти ПР» коли по сумарному діффу ніць не можна зрозуміти, що там взагалі діялось.

Ви серьезно в таких моментах робити окремий комміт на зміну назви в функції? Навіщо? Просто шоб красивий коміт був?

Саме щоб коміт був легко і повністю зрозумілий і придатний для перевірки, як очами, так і автоматизовано (наприклад, пошукати в проєкти стару назву).

І да, після цього можна назвати коміт «красивим». Красиве те, що функціональне.

В мене наприклад і у всіх з ким я працював за 8 років, назва функції може змінитись у будь-якому коміті з купою інших ченжів. Але мене це не бентежить бо я ревьюваю Пулл Реквести (як і всі з ким я працював)

І як ви тоді розумієте, що ж саме сталось у ПР?
Який у вас максимальний розмір такого ПР у змінених рядках?

Назвіть вебморду, якою користуєтесь.

GitHub

І я не розумію, як можна «ревʼюїти ПР» коли по сумарному діффу ніць не можна зрозуміти, що там взагалі діялось.

Це як не можна? У вас ченжи у коді роблять усе підряд і у всьому і про все? Так це тоді, знову ж таки, до процессів і декомпозиції задачі

Ось про те і стаття, як зробити історію, щоб такого не було.

Не зрозуміло для чого (окрім кейсу шо ви описали з «командую зверху»), коли є функція Пулл Реквестів і сквошу

Саме щоб коміт був легко і повністю зрозумілий і придатний для перевірки, як очами, так і автоматизовано (наприклад, пошукати в проєкти стару назву).
І да, після цього можна назвати коміт «красивим». Красиве те, що функціональне

У вас інше бачення, я ревьюваю Пулл Реквести, діф коду, який мерджиться у репу, а не «діф коміту, який був годину тому»

І як ви тоді розумієте, що ж саме сталось у ПР?

Знову ж таки, діф коду прекрасно показує шо змінілось.

Який у вас максимальний розмір такого ПР у змінених рядках?

Зазвичай все що вище 1000 (виключаючи сгенерований код генераторами ітп) — то таке у нас декомпозують на декілька ПРів

GitHub

А, ну серед цього набору він майже найтупіший. В нбому дійсно дивитись декілька комітів в ланцюжок, порівнювати версії і т.п. вкрай незручно, і викладати кожну таку дію в окремий PR — єдиний спосіб контролювати процес.

Ну так на то він і попса для тих, кому Git серед всіх VCS корисний офлайн-зберіганням.

Це як не можна? У вас ченжи у коді роблять усе підряд і у всьому і про все?

Я вже наводив приклад. Щось видалили, щось порефакторили, щось додали, а ще й переформатували один файл, бо раніше чомусь не зробили це. Зрозуміти щось в такій брудній каші не можна. До чого тут домисли про «усе підряд у всьому»?

У вас інше бачення, я ревьюваю Пулл Реквести, діф коду, який мерджиться у репу, а не «діф коміту, який був годину тому»

І як це протирічить тому, що я кажу?

Знову ж таки, діф коду прекрасно показує шо змінілось.

Ні, не «прекрасно». Він показує все в купі.

то таке у нас декомпозують на декілька ПРів

О, ну ось про це я і питав. Якщо засіб не дає інакше — а GitHub тут примитивнійший за всіх (може, Bitbucket тупий на тому ж рівні, і все) — нема виходу ніж розбивати на роздільні PRи.

Ні, не «прекрасно». Він показує все в купі.

Не бачу в цьому проблеми. Для цього і робиться Пул реквест

О, ну ось про це я і питав. Якщо засіб не дає інакше — а GitHub тут примитивнійший за всіх (може, Bitbucket тупий на тому ж рівні, і все) — нема виходу ніж розбивати на роздільні PRи.

Справа не в гітхабі, а в тому шо ви юзаєте коміти, які не мають відповідати за структуровані ворклоги, як тіж самі Пул Реквести для декомпоузу і ревью. Коли по суті там можуть писатись і переписуватись куски які уже запушені до цього.
Я працював зі всіма гіт сервісами, і ніколи не було потреби дивитись окремі коміти коли я ревьюваю ПР

Я вже наводив приклад. Щось видалили, щось порефакторили, щось додали, а ще й переформатували один файл, бо раніше чомусь не зробили це. Зрозуміти щось в такій брудній каші не можна. До чого тут домисли про «усе підряд у всьому»?

Як це не можна? Ви шо там пів системи в одному ПРі переписуєте? Якшо так то питань нема, але можна і декомпоузнути тоді.
Я просто не вірю шо ви не можете за процессити той діф і потрібно йти у коміти

Як це не можна? Ви шо там пів системи в одному ПРі переписуєте?

Ну ось ви знову про PR.

Мені здається, що щоб ви зрозуміли, про що і як стаття і про що і як я писав, треба всюди, де у мене або автора статті «коміт», думати про окремий PR. Тоді ми дійсно можемо на чомусь зійтись. А інакше ви ніяк не відмовитесь від ідеї, що весь ланцюг комітів треба розглядати тільки цілком як єдину зміну з єдиним діффом.

шо ви юзаєте коміти, які не мають відповідати за структуровані ворклоги

І це підкріплює моє припущення — бо чогось коміти «не мають відповідати за структуровані ворклоги»

Я просто не вірю шо ви не можете за процессити той діф і потрібно йти у коміти

А після такого мапінгу — повірите?

Мені здається, що щоб ви зрозуміли, про що і як стаття і про що і як я писав, треба всюди, де у мене або автора статті «коміт», думати про окремий PR.

Та не, все я зрозумів. Я кажу шо зв`язка PR + squash commits дає красиво історію і менше гемору. А робити красиві коміти шоб була гарна історія для ребейзу — шоб було естетично і гарно?
Ну ок, але навіщо коли є сквош і кожний коміт == ticket number. Не ясно

Ну ок, але навіщо коли є сквош

Ну значить вам ще не доводилось бачити після сквошу брудну суміш, яку просто не можна зрозуміти. Повезло. Чи якось інакше щось інше оберігає.

Мені доводилось, і після цього нормально різати на атомарні верифіковні тестовні коміти — неминуча норма.

Ну ок, але навіщо коли є сквош і кожний коміт == ticket number.

А потім з’являться новий ticket number перенести частину функціоналу в інший бранч. А там половина є, а половини немає.

якшо засквошити то і буде один атомарний коміт. і ребейз не потрібний

Ось у вас, наприклад, історія в комітах:
1) Переформатували файл, якого давно не торкались.
2) Видалили код, який втратив користь і заважає рефакторінгу.
3) Рефакторінги, два простих і один складний.
4) Додавання бібліотечного коду задля фічі.
5) Наприкінець, додавання самої фічі.

Якщо ви все це засквошите в один коміт і мене це стане у перешкоду... ну я перший почну бити вас ногами, поки не підпишете, що не повернетесь в IT.

Якщо в ваших процесах це все не одна задача (тікет) а пʼять різних, і відповідно пʼять комітів — ок, мапінг понять прийняв, але ваші процеси перевантажені.

Ось у вас, наприклад, історія в комітах:
1) Переформатували файл, якого давно не торкались.
2) Видалили код, який втратив користь і заважає рефакторінгу.
3) Рефакторінги, два простих і один складний.
4) Додавання бібліотечного коду задля фічі.
5) Наприкінець, додавання самої фічі.

Окей, ви так працюєте, красиво комітите. В реальному світі між цими 5 красивими декомпозованими комітимами можуть встряти шось по типу «fix lint» бо локально чогось у вас нема по лінту що є на пайплайні.
Але так чи інакше — (кажу про себе і з ким працював) ніхто ніколи не йде дивитись коміти, а сразу відкриває діф в ПРі і там ревьюває
Бо нема сенсу, так як ти можешь змінити теж саме місце в наступному коміті і виходить що час на ревью втраченний на зміни, яких уже нема. Це просто не має сенсу

Якщо в ваших процесах це все не одна задача (тікет) а пʼять різних, і відповідно пʼять комітів — ок, мапінг понять прийняв, але ваші процеси перевантажені.

дивлячись якого масштабу вас зміни, якщо оце все потягне на 10к рядків то без питань — треба окремі таски/пулл реквести і максимум декомпоузу, бо буде важко ревьювати.

Мені здається шо ми обидва згодні шо декомпоуз потрібний, моя позиція просто шо коміти — не найкращий кандидат на декомпоуз, так як можна і просто пулл реквести зробити, а коміти, це фіксація зміни у гілці, не більше (якщо про feature branch казати)

В реальному світі між цими 5 красивими декомпозованими комітимами можуть встряти шось по типу «fix lint» бо локально чогось у вас нема по лінту що є на пайплайні.

Будуть додані до тих комітів, що перед цим щось зламали. (Якщо це не випадок, коли воно стриггерилось тільки коли якийсь файл зачепило.)

Бо нема сенсу, так як ти можешь змінити теж саме місце в наступному коміті і виходить що час на ревью втраченний на зміни, яких уже нема. Це просто не має сенсу

Цього не зрозумів.

Мені здається шо ми обидва згодні шо декомпоуз потрібний, моя позиція просто шо коміти — не найкращий кандидат на декомпоуз, так як можна і просто пулл реквести зробити

Ось, повторююсь, це тому, що ваш досвід, як я розумію, обмежений гітхабом, а в гітхабі зручних варіантів зробити якісно і зрозуміло нема, ніж робити окремими PR.

У мене інша історія — я фактично засвоював складні форми роботи з Git маючи не GitHub, а Gerrit. Він з самого початку мав такі засоби, як ланцюжки ревʼю і порівняння ревізій одного ревʼю, і на нього rebase накладається майже ідеально. Ну і там, де це робилось, не було вимоги один тікет = один коміт. Інші морди, як той же GitHub або Bitbucket, були пізніше, і їх обмеженість неприємно вразила.

Будуть додані до тих комітів, що перед цим щось зламали. (Якщо це не випадок, коли воно стриггерилось тільки коли якийсь файл зачепило.)

Це як ? Типу ви ще сквошите коміти в коміти шоб коміти були красивішими? Ну окей, але це не дуже продуктивно імхо. Якшо у вас такі процесси на проекті то ок, але я таке вперше чую, шоб для ПРу готували спеціально красиві коміти

Цього не зрозумів.

commit 1 — changed line 100 in file 1
commit 2 — added file 2
commit 3 — changed line 100 in file 1 again (ну от захотілось бо треба)
я про такі кейси
В ітогу коміт 1 уже не релевантний , а витратили час на line 100 якої і так уже нема/змінена
Чому б в такому разі не глянути на весь діф зразу в Пул реквесті?

У мене інша історія — я фактично засвоював складні форми роботи з Git маючи не GitHub, а Gerrit. Він з самого початку мав такі засоби, як ланцюжки ревʼю і порівняння ревізій одного ревʼю, і на нього rebase накладається майже ідеально. Ну і там, де це робилось, не було вимоги один тікет = один коміт. Інші морди, як той же GitHub або Bitbucket, були пізніше, і їх обмеженість неприємно вразила.

Звичка — це вже інше зовсім інше. З цим ніякі аргументи не поспорять

Це як ? Типу ви ще сквошите коміти в коміти шоб коміти були красивішими?

Вважайте, да. Але не «красивішими» а щоб відповідали одній цілі, атомарно описували зміни і були тестованими (якщо CI вимагає щоб кожний коміт проходив тести — нормально це так).

але я таке вперше чую, шоб для ПРу готували спеціально красиві коміти

Історія має бути такою, щоб кожна зміна була зрозуміла, коректна, придатна для верифікації, відділення (і реверту, якщо треба), і тестування. Можете звати це «красивими» комітами. І да, треба так готувати — для більшости задач і проєктів.

commit 1 — changed line 100 in file 1
commit 2 — added file 2
commit 3 — changed line 100 in file 1 again (ну от захотілось бо треба)
я про такі кейси
В ітогу коміт 1 уже не релевантний , а витратили час на line 100 якої і так уже нема/змінена
Чому б в такому разі не глянути на весь діф зразу в Пул реквесті?

Якщо така зміна в commit 1 не була принципово чомусь окремою, то коміти треба склеїти.

Якщо ж вона була принциповою, то аналізувати коміти треба роздільно, по сумарному PR не зрозуміти, що діялось, або надто дорого.

Звичка — це вже інше зовсім інше. З цим ніякі аргументи не поспорять

Я не про звичку, а про співвідношення понять і про доступний функціонал.

З таким слабким (саме в плані аналізу окремих комітів) сервісом, як GitHub, технології, описані в статті, вимагають ремапінгу — по PR на коміт. Але тоді і побачити разом весь ланцюг і проаналізувати його — не можна.

Ну... треба лише сказати, що rebase доволі обмежений, редагування diff-а це окреме мистецтво, про яке не сказали взагалі. Також... про збереження даних треба думати при наявності даних. Тому, щоб не лазити по ref-логу, рекомендую відразу створити гілку для поточного стану. Також, інколи простіше редагувати через cherry-pick.

Шось я так і не зрозумів чому «погана» історія це проблема. Історія вона на те і історія, щоб розуміти що і як відбувалось у проекті, і потім коли буде реально треба — то знайти хто саме і коли саме щось зламав. Тому що історія справжня, а не підробна. Я досить уважно читав статтю, і окрім перфекціонізма — не бачу причин для чого це робити. А ось мінуси є — чесна історія завжда краще при пошуку проблем.

Є репозиторій з купою комітів і мержів — ну то і шо ? Тобі ж цей репозиторій потім не на базарі продавати. Те що в репозиторії є коміти типу:

«commit1», «commit2», «final-final-fixed», до «try again pls»

чи гілки типу

hotfix/hotfix/fix-final-really-final-2

вирішується тим що гілки створюються по якійсь системі, типу там окрема гілка під окрему таску в Джирі, а текст комітів пишеться з розумом (ШІ в допомогу).

А аргументи про те шо ревьювер повинен дивитись коміти по одному і йому незручно, чи в нього п’ять хвилин до стендапу — ну то просто смішно. Історія пишеться не для ревьюверів, а для того щоб трекати що саме відбувалось у проекті.

А ще чомусь нічого не сказано про те, що коли декілька людей активно комітять в одну гілку, а потім хтось вирішує що якось воно некрасиво і треба зробити rebase і погратись з історією, то потім вся команда що працювала з цією гілкою розбирається хто ж там що зробив з історією, і що треба зробити локально щоб нарешті push пройшов.

Іноді треба щось знайти в гіт логах. Але на практиці нікому нема діла що там робилось в твоїй власній бранчі. Git squash & merge — і чистота історії гіта на рівні master/main. +cleanup старих бранчей в CI/CD, якщо автоматично не видалились після мержа.

Шось я так і не зрозумів чому «погана» історія це проблема. Історія вона на те і історія, щоб розуміти що і як відбувалось у проекті, і потім коли буде реально треба — то знайти хто саме і коли саме щось зламав.

Для мене погана історія проблема, бо навіть мені важко зрозуміти, чи я чогось не зламав. Мова ж не йде про те, що ми перепишемо коміт річної давнини, завичай rebase це історія однієї задачію, останнього тижня. Тому якщо ти бачиш помилку у своєму коміті, то чому б її не виправити в цьому ж комміті?

Це також повага для тих, хто буде робити рев’ю. Атомарні коректні коміти переглядати одна насолода. Ти бачиш усі зміни крок за кроком. А так у тебе є вибір, або побачити плюс/мінус тисячу рядків коду. Або дивишся на коміт, бачиш помилку, тегаєш її, а розробник — це не проблема, я виправив її через 10 комітів.

Особисто для мене, rebase це також рев’ю моєї роботи, і на цьому етапі я часто знаходжу помилки.

Історія вона на те і історія, щоб розуміти що і як відбувалось у проекті, і потім коли буде реально треба — то знайти хто саме і коли саме щось зламав.

Тому що нікому не треба буде знати, що я спочатку з 10 місць де треба поміняти поміняв тільки 8, бо боліла голова, тільки потім в тесті знайшов ще 2 і тоді додав їх. Або що спочатку накидав коду на фічу, і тільки потім зрозумів, що треба в бібліотеці розділити функцію на дві і додати аргументів до іншої. Такі подробиці особистого життя розробів нікому не потрібні.

А ось коли прийняли в спільну гілку — тоді історія вже фіксується і тоді і стає принциповим знати, «хто саме і коли саме щось зламав».

Я досить уважно читав статтю, і окрім перфекціонізма — не бачу причин для чого це робити. А ось мінуси є — чесна історія завжда краще при пошуку проблем.

Вона і буде чесною, та історія.

А аргументи про те шо ревьювер повинен дивитись коміти по одному і йому незручно, чи в нього п’ять хвилин до стендапу — ну то просто смішно. Історія пишеться не для ревьюверів, а для того щоб трекати що саме відбувалось у проекті.

А зрозумілі коміти — у першу чергу для ревʼюєрів (включаючи себе ж). Нічого смішного.

А ще чомусь нічого не сказано про те, що коли декілька людей активно комітять в одну гілку, а потім хтось вирішує що якось воно некрасиво і треба зробити rebase і погратись з історією, то потім вся команда що працювала з цією гілкою розбирається хто ж там що зробив з історією

Зазвичай так не працюють, це вже ви видумали — і, здається, тільки щоб позаперечувати. Git дозволяє «Recovering from upstream rebase», є секція в документації. Але такий стиль використовують тільки в особливих процесах, яких не буває в звичайному проєкті.

Дякую, хороша стаття. Хотів би додати пару пунктів
1. rebase можна робити якщо працюєте в бранчі в самі, бо команда міняє hash комітів. І інший розробник буду не радий в вашій бранчі виконати git pull
2. git rebase -i дійсно класний інструмент коли треба підчистити commit message
3. частково читабельність комітів вирішується на стороні сервера git хуками. В гітлаб є окрема опція з регекспом якщо не помиляюсь

Дуже цікава стаття з гарними прикладами. Авторці респект!

Гарна стаття. Мене познайомили з ребейзами на поточному проєкті. Я спочатку не розумів нахіба, але коли втягнувся — не розумію, як можна ним не користуватись? Чисті, гарні, логічні коміти — зрозуміла історія!

Чисті, гарні, логічні коміти — зрозуміла історія!

звучить як сквош коміти tbh

Ніт. Сквош при більш-менш обʼємних і різнопланових змінах це як раз тотальний бруд, в якому нічого не можна знайти і зрозуміти, і можна тільки тестами перевіряти, що ж воно таке коїлось.

Підписатись на коментарі