Коли дрібниці важливі. Пишемо коміти в Git

Усім привіт, мене звуть Ілля, я Software Engineer у Dev.Pro. Ця стаття — про коміти та їхню надважливу функцію у житті розробника. Вона стане у пригоді тим, хто хотів би навести лад у git history і changelogs, а заодно поліпшити комунікацію.

In case of fire git commit → git push → git out.

Цей колись смішний жарт бачила, мабуть, кожна людина, що має хоч якийсь стосунок до IT. Коміти — це цінна штука, але водночас буденна, хоча так було не завжди. Ще кілька років тому заливати зі схрещеними пальцями апдейти по FTP було так само поширеною практикою, як сьогодні «коміт → пуш → додомку». І якщо з останніми двома кроками все більш-менш зрозуміло, то про те, як робити класні коміти, нерідко виникають суперечки.

Ілюстрація Аліни Самолюк

Основи

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

  1. Відділяйте заголовок коміта від його тіла порожнім рядком.
  2. Пишіть заголовок, що містить не більше як 50 символів.
  3. Починайте заголовок з великої літери.
  4. Не ставте крапку в кінці заголовку.
  5. Не пишіть у рядку тіла коміта більше ніж 72 символи.
  6. Позбудьтесь непотрібних знаків пунктуації.
  7. Додавайте тіло коміта тільки за потреби: текст має пояснювати зміст змін.
  8. Використовуйте імператив у заголовку.

Приклади того, яким має бути коміт згідно з цими рекомендаціями, ретельно розібрані у цій статті.

Більшість рекомендацій тісно пов’язані з правилами англійської граматики та командами git format-patch та send-email. Наприклад, порожній другий рядок означатиме, що перший — це заголовок листа, а все інше — сам текст повідомлення. Правило про довжину рядка залишилось на пам’ять від старих терміналів з обмеженням ширини у 80 символів і відповідного робочого етикету. А правило про імператив у заголовку виведено для того, щоб успадкувати тон автоматичних комітів, які генеруються самим Git під час merge/revert операцій.

Список ніби зрозумілий, і навіть є мотивація за кожним із цих пунктів. Але ось проблема: ці правила були описані у 2008 році. Тобто 12 років тому. Для ІТ — ціла ера, чи не так?

Як це працює сьогодні

За цей час зазнало змін майже все. І точно змінився набір інструментів, які використовують команди під час розробки: починаючи від каналів комунікації, як-от Zoom і Slack, і до IDE, які сьогодні можуть значно більше, ніж 2008-го. Змістився і фокус уваги кодера: більше не потрібно шукати правди в коментах до коду або в тексті коміту: процес розробки став доволі цілісною штукою з вибудованою інфраструктурою. Середньостатистичний аутсорс-проєкт радше користується JIRA і Bitbucket, а не розсилкою патчів електронною поштою. Так що, якщо потрібно щось прочитати чи дізнатись, я просто відкриваю тікет і читаю. Або вікі, або ще щось, що під’єднане до інфраструктури проєкту.

Звісно, для маленьких проєктів, які люди пишуть для себе і не планують нікому показувати, найголовнішим, найімовірніше, залишиться критерій зручності для автора. Цікавіше поговорити про роботу з іншими людьми. Мій перший вчитель в IT навчав так: «Пишіть код таким чином, ніби після вас його буде підтримувати людина з маніакальними садистськими нахилами». Ми сміялися з цього: ну хіба ж може таке бути, щоб в IT працювали маніяки? Тут же всі такі гарні, розумні й милі!

Виявилось, що «маніакальні» здібності можуть прокинутись і в тобі самому, особливо тоді, коли бачиш коміт, в якому автор змінив 12 файлів в ядрі й лаконічно написав WIP. Яка саме робота була «in progress» в той момент, коли цей коміт з’явився, і які цей код розв’язує задачі, доведеться здогадуватись без пояснень. Схоже трапляється через те, що немає жодних домовленостей щодо того, якими мають бути коміти. Щоб такого не було, треба це узгоджувати.

У кожному конкретному випадку домовленості можуть трохи відрізнятися, але принцип буде схожим: коміту потрібен формат. Якщо він відповідає цьому формату — коміт ок, якщо ні — не ок. Постає питання: як визначити цей формат і як перевіряти коміт на відповідність.

Є кілька опцій:

  • Щоб не вигадувати черговий велосипед (хіба нам своїх мало?) можна взяти за основу той самий формат, яким користується більшість, або ваш основний фреймворк. Наприклад, пишете на Angular — подивіться, як вони комітять код свого фреймворку, може, в них є політика або гайдлайн.
  • Можна пошукати якийсь відомий підхід з хорошою документацією. Наприклад, Conventionalcommits.org. Він добре описаний, має достатню кількість посилань на різний допоміжний тулінг, а ще його автори хоча й пишуть, що базують концепцію на попередньому пункті, але все ж не прив’язуються ні до якого фреймворку. Так що його можна використовувати будь-де, не витрачаючи час на відповіді на закономірні запитання типу «чому у нас проєкт на PHP, а conventional commit — ангулярівський?».
  • Виходити з можливостей своєї інфраструктури. Майже всі користуються JIRA, чи не так? А точніше навіть JIRA+Bitbucket. У них є такий зручний інструмент — смарт-коміти. Якщо коротко, то одним комітом можна затрекати час, залишити коментар до відповідного тікета і змінити йому статус. Усе, що треба — дотримуватись формату й налаштувати цю фічу на своєму проєкті.

Усі вищенаведені варіанти — про формат заголовку. Перевірка на відповідність формату виконується за допомогою pre-commit hooks, які порівнюють текст із певною регуляркою. Наразі одним із найпопулярніших git hook runner + linter рішень є поєднання husky і commitlint.

В результаті матимемо husky pre-commit hook, який буде спрацьовувати щоразу, коли автор хоче зробити коміт, commitlint, який буде дивитись на свої конфіги й перевірятиме, чи відповідає текст коміту усім зазначеним правилам.

Такий простий сетап вирішує цілу низку питань: від загальної невизначеності щодо формату комітів до конкретних проблем з боку CI. Наприклад, одного разу специфічні для Windows символи, що потрапили в коміт-меседж із домашньої машини одного із тіммейтів, виявились сильнішими за build-скрипт. Зрозуміло, що це можна вирішити різними способами, але чи не краще розв’язувати проблеми саме там, де вони виникають?

Коли проблеми вирішено, варто перейти до питань автоматизації релізів. Це також дуже зручно робити, якщо у вас є домовленість про формат комітів. Припустимо, ви узгодили, що є задачі трьох типів: fix, task, improvement. Також ви погодили, що формат коміту матиме таку схему: type(scope?): subject, де type — це тип задачі, scope — домен або частина проєкту, до якого вона належить. І subject — це, власне, те, які зміни відбулися. Додавши до цього інструменти автоматизації, отримаємо зручні й вичерпні release notes для кожної нової версії. Вони матимуть приблизно такий вигляд:

Гарно, правда? Цей слайд взятий з чудової презентації Mario Nebl.

Замість висновків

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

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

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

Отже, якісний коміт у 2020-му це:

  1. Обговорений і закріплений формат.
  2. Pre-commit хуки і лінтер.
  3. Номер задачі в таск-трекері в заголовку коміта.
  4. Список змін у тілі коміта.


P.S. Я працюю у великій команді, хуки у нас були не завжди, й можу на власному досвіді стверджувати, що рішення про використання їх у репозиторії було дуже важливим. Ми почали писати однакові коміти, і відпала купа дивних проблем. Тож, якщо ви ще не мали нагоди їх застосовувати або якраз думаєте про це, дуже рекомендую. Часу на інтеграцію обмаль, а вплив і зростання якості важко переоцінити!


Щоби не пропустити нові статті Іллі Хлєбова — підписуйтеся на нього у телеграм-боті Стрічки DOU.

Похожие статьи:
З початком повномасштабної війни та евакуації IT-компаній Харків втратив значну частину своєї техноспільноти. Наскільки все погано...
У першому після початку російського вторгнення інтервʼю DOU міністр цифрової трансформації Михайло Федоров розповідає, що 80% його...
Привіт, мене звуть Максим Чувпилов. Я працюю продакт-менеджером у Wix і останні два роки займаюся рекрутментом продактів...
Договори без звички читати складно. Їх написано формалізованою мовою, вони довгі й часто містять фрактальні уточнення...
У випуску: нові релізи Pandas та NumPy без підтримки Python 2.x; пошук паркомісць з deep learning; огляд PEP 572. Новини Pandas припинить...
Яндекс.Метрика