Comments 84
fix(products): поправить длину строки с ценой
Часть заголовков неправильно отображается в мобильной версии из-за ошибок
в проектировании универсальных компонентов.
МЕТА ДАННЫЕ: SECRETMRKT-578, SECRETMRKT-602
Мне кажется, что тут возникла небольшая ошибка. Коммит — не то, что должно быть сделано, а то, что уже сделано. Что нужно сделать должно быть написано в таске где-то или в требованиях. Как я понял, в этом примере такая информация находится в SECRETMRKT-578, SECRETMRKT-602. Т.е. верный вариант будет
fix(products): поправлена длина строки с ценой
Часть заголовков неправильно отображались в мобильной версии из-за ошибок
в проектировании универсальных компонентов.
МЕТАДАННЫЕ: SECRETMRKT-578, SECRETMRKT-602
И тогда автоформирование Change Log уже взлетит само собой.
UPD: Да, не дочитал. В статье об этом есть в конце. Но мне всё равно кажется это несколько странным.
If I (merge|cherry-pick|rebase|use|...) this commit it will (commit message):
If I use this commit it will «Add logout button to home page».
Это позволяет мейнтейнерам буквально по кусочкам собирать нужную цепочку из сотен коммитов и веток.
По-русски, наверное, стоит перефразирвать, т.к. слова меняются из-за склонения и времени.
На русском повелительное не приживётся в коммитах — просто потому, что сами мы в разговоре никогда так коммит не опишем. Коммит это выполненная работа, и всегда описывается как "что было сделано", "что изменилось". Я сам за следование какому-то соглашению, но оно должно выбираться так, чтобы вызывать минимальное сопротивление, быть достаточно близко к тому, что люди склонны использовать и без явных соглашений — потому что наличие соглашения намного важнее его конкретики. (И под "на русском" я имею в виду не язык, на котором пишется сообщение коммита, а язык, на котором думает программист.)
Правки внутри рабочих веток удобно именовать в стиле бортового журнала (т.е. как угодно), т.к. они отражают ваш путь решения задачи. Чем сложнее задача, тем путь может быть более удивительными и непредсказуемым. Здесь главное не мешать творческому процессу — чем меньше церимоний тем лучше. Во время squash все эти шаги будут удалены или переписаны.
Если вдруг покажется, что вливаемые в master изменения слишком крупные или слишком мелкие, или неочевидные, то значит херня творится на уровне постановки задач. Может в работу под видом задачи на разработку попадают сразу стори или целые эпики, или какие-то невнятные хотели. В таком случае дрючить разработчиков за именоваание комитов бесполезно.
Я понимаю что проблема тут кроется во владении английским языком, у всех разный уровень и язык надо учить, но все таки на родном языке стали получаться более осознанные описания изменений.
Думаю это целая тема для обсуждения, вот мои соображения, которые являются результатом многократных споров и обсуждений с моими коллегами.
Для коммитов на русском языке просто следовать этому правилу: "Используйте повелительное наклонение", будет не благозвучно и думаю не правильно с точки зрения русского языка, тут говорится: "Use the imperative mood in the subject line" и поясняется, что заголовок должен быть продолжением фразы: "If applied, this commit will your subject line here", пример:
If applied, this commit will update getting started documentation
В случае применения этого коммита будет обновлено руководство по началу работы
Без начала предложения т.е. без глагола will
в английском языке получается imperative mood
:
update getting started documentation
обновить руководство по началу работы
а в русском языке, если не ошибаюсь, это инфинитив:
обновить руководство по началу работы
обновить конфигурацию commitizen
добавить хук забытый в прошло коммите
а повелительное наклонение образуется иначе:
обновите руководство по началу работы
обновите конфигурацию commitizen
добавьте хук забытый в прошло коммите
Если следовать трюку с продолжением фразы, то данное правило можно свести до:
Заголовок комментария должен формулироваться, как продолжение фразы: В случае применения этого коммита будет...
В таком случае комментарии получаю такой вид:
обновлено руководство по началу работы
обновлена конфигурация commitizen
добавлен хук забытый в прошло коммите
исправлена ошибка…
добавлена возможность…
улучшена возможность...
Я далеко не эксперт в русском и тем более в английском, но определенно такой подход более логичный во всех смыслах история лаконично читается и на ее основе можно генерировать список изменений.
Мне будут очень интересны другие мнения на эту тему.
ЗЫ
обновлять руководство по началу работы
обновлять конфигурация commitizen
добавлять хук забытый в прошло коммите
исправлять ошибку
добавлять возможность
улучшать возможность
При применении этот коммит будет обновлять руководство
Так обновит в итоге или нет? Несовершенный вид, как мне кажется, тут вообще не подходит.
Несмотря на это, меня почему-то смущает активная позиция коммита.
Интуитивно я бы предпочёл в качестве актора видеть атора коммита. «Этим коммитом я…
*… исправил ошибку»
*… добавила фичу"
*… увеличил производительность"
*… упорядочила отступы"
Кто-то может возразить, что это обращает необоснованно много внимания на личность автора, даже пол его тут проявляется. А по мне, это даже плюс. Чьи-то коммиты нужно перепроверять 100 раз, и запашок от них идёт на версту, а чьи-то и смотреть незачем — там всё хорошо, правильно и ровно.
А на русском выглядит очень странно. Да.
1. Список изменений (changelog.md) генерируете на основе истории или нет (есть мнение, что это не лучший способ), какой подход у вас к созданию и поддержке истории изменений?
2. Применяете git-flow или свой поход? Расскажите подробнее.
3. Интересно как относитесь к линейной истории это полезно или нет? Мое мнение, что линейная или частично линейная история дает массу профитов и даже применяя git-flow история может быть линейная, если приложить немного усилий, но мало кто видит в этом преимущества, давно хочу понять почему. На текущий момент гипотиреоза в том, что мало кто использует историю как инструмент анализа или может быть есть иной способ сохранить блейм или анализировать историю в незавидности от ее линейности.
keepachangelog.com/en/1.0.0
1. Change Log не ведем, есть Release Notes. Перед каждым Pull Request-ом разработчик заполняет в файле ReleaseNotes.md следующие пункты:
— New (Что нового? (фичи, новая функциональность));
— Improvements (Какие улучшения мы добавили в существующие фичи);
— Fixes (Список исправленных багов);
— Operations (Eslint, обновление библиотек и т.д.).
На основе этого файла формируются Release Notes каждой версии. Этот документ смотрят QA специалисты. После публикации версии содержимое файла ReleaseNotes.md обнуляется.
2. Выбрали классический git-flow (хотя сам я сторонник другого ветвления). Это правильно по многим причинам, но для меня главная — открытость к ротациям в команде. Отраслевые стандарты позволяют свести начальный инструктаж к минимуму.
3. Не задумывался линейна или не линейная история. Использую в работе удобный GitKraken, всё наглядно. За ссылки благодарю, изучу внимательно этот вопрос.
1. Перед каждым Pull Request-ом разработчик заполняет в файле ReleaseNotes.md
Это один файл на проект? Учитывая конвенцию и генерацию коммитов что мешает это файл формировать автоматически?
2. Выбрали классический git-flow (хотя сам я сторонник другого ветвления)
Другого ветвления, это какого?
Учитывая Ваш опыт применения git-flow, представите, что будет с историей, если каждый разработчик будет синхронизировать свою рабочую ветку не слиянием с develop, а через перемещение
git pull --rebase origin develop
?Ребейз перед мержем в мастер у нас прям обязателен, потому что лучше разрешить все конфликты до мержа, но получаются force пуши в ветки.
--ff делает так, чтобы были видны мёрж коммиты?
Мы решили, что лучше он будет всегда.
да. --ff выключает поведение при котором merge коммит не сделается, если его можно не делать.
Я, может, чего-то не понимаю, но это поведение --no-ff
--no-ff
Create a merge commit even when the merge resolves as a fast-forward.
А --ff как раз мёрж коммиты может не создавать
--ff
When the merge resolves as a fast-forward, only update the branch pointer, without creating a merge commit.
Цитаты вот отсюда https://git-scm.com/docs/git-merge
Типичный случай. Нужно пофиксить сложный баг — в первую очередь иду смотреть историю гита, анотации. Если микрокомиты с тегами — то все легко, сразу видно коммит в имени которого сразу прикреплен номер таски по которому эти изменения были сделаны и почему, даже если они были сделаны 5 лет назад. А уже в таске все прописано, аналитика, какие кейсы для воспроизведения, и почему конкретно было принято такое решение.
А если это левый мердж, в котором под сотню ченджей, без тикета и тегов — то и смотреть бесполезно.
А список ченджей он никому то и не нужен, написать можно всякое
git blame
это отдельная история в теории за его формирование отвечает правила по оформлению кода и текущие конвенции не решают этот вопрос полностью, в общем это отдельная тема.Номер таска в комментарии полезен но не всегда, название бага и описание нежелательного поведения формирует тестировщик, а разработчик для решения может изменить совсем не связанный с описанием компонент или компоненты.
Поэтому в политику формирования истории полезно добавлять правило: фиксировать изменения разных компонентов отдельно, отдельно фиксировать рефакторинг отдельно фиксировать решение, если ему предшествует рефакторинг и дополняя конвенцией по формированию комментария получаем полезную историю.
Но это не решает вопроса аннотации тут нужен опыт, дополнительная конвенция или правила по оформлению кода которые это учитывают.
Мы тоже хотели навести порядок в коммитах, но потом поняли что мы не смотрим историю. Зачастую, когда смотришь историю, интересен ответ не "что было сделано?", а "почему так было сделано?". На второй вопрос можно получить ответ из постановки задачи и из инструмента для код ревью. Для того чтобы найти и то и другое нам достаточно номера тикета в коммите.
Области по своей природе могут смешанными при каких-то сложные и больших правках. Переход на новые библиотеки, утилиты сборки, какой-то глобальный рефакторинг и т.п.
Смешанные типы это в общем случае плохо, но для маленьких проектов практически неизбежно, т.к. строгое следование лучшим практикам может трудоёмкость в небеса и сделать такие проекты бессмысленными.
В таких случаях лучше предусмотреть возможность.
Кстати, в какой-то момент времени оказалось, что комментарии коммитов этого хорошо, но нужен внятный независимый ченжлог. Прикрутил его формирование по коммитам. А потом оказалось, что удобнее сделать наоборот — генерировать комментарии по изменение ченжлога. Нужно сказать, что некоторое время было прямо счастье. И в больших и в маленьких и даже в микро-проектах дописывает правишь текстовый ченжлог (по правилам -с разделением на фичи/баги и т.п.), потом делаешь коммит и комментарий генерируется из изменений ченж-лога. Одновременно переформатируется сам ченжлог — добавляется информации о дате коммита, номере сборки, статусе релез/дебаг и т.п. А при коммите в релиз всё это автоматически собирается (от прошлого релиза) ещё раз переформатируется, собирается в один большой список изменение, снабжается версией, генерируется комментарий в коммит. Очень удобно было! Имеешь текстовый файл с описанием основных изменений, имеешь список изменений для релизов и т.п.
Но всё держалось на мега-скрипте для баша, который со временем превысил предел сложности, развалился не несколько версий и т.п. А духу и времени всё это облагородить и переписать на каком-нибудь пайтоне не находится. В результате в новых проектах снова обычные комментарии к коммитам :(
Смешанные области просто не надо указывать вообще. Смысл указания области в том, чтобы можно было легко пропускать коммиты, которые явно не представляют интереса. Если сложно чётко описать, что затрагивает коммит, а что нет — просто не надо указывать ничего. Если коммит затрагивает пару областей — никто не запрещает указать обе через запятую: "fix(this,that): something".
Смешанные типы никак не связаны с размером проекта, они связаны с внутренней дисциплиной разработчика. Следуя Вашей логике маленьким проектам и git не нужен.
В таких случаях лучше предусмотреть возможность.
Не лучше. Если стандарт изначально предусматривает возможность на него забить — от него вообще пользы не будет, он просто добавит бессмысленной бюрократии и всё.
Что значит забить на стандарт? Никто не призывает «забить». Но под стандарт пуштся парсеры и утилиты. И если в реальном мире есть какая-то ситуация, а стандарт её не предусматривает, то это хреновый стандарт и от него будут в этой ситуации отступать. Или просто будут использовать какие-то другие соглашения.
Стандарт, он не для того, чтобы разработчиков дрессировать. Он для того, чтобы можно было различные утилиты совместимым образом автоматизировать. А вопросы, что и когда можно, а что нельзя решают договорённостями в каждой конкретной команде под её конкретные потребности.
Вот, я например, не могут делать один коммит на одну область/тип. Просто потому, что нет у меня таких ресурсов под такие небольшие проекты. И это популярная ситуация. На самом деле матёрый энтерпрайз это скорее исключение, чем правило и большинство команды вынуждено идти на компромисы. По крайней мере до тей пор, пока проекты не достигнут определённой степени зрелости и/или коммерческого успеха. Значит они (и я в их числе) будут городить свои костыли. Писать несколько областей или типов через запятую, скорее всего. И все утилиты я будут пилить под это. Но это рушит совместимость, обесценивает и ограничивает стандарт. А если окажется, что что-то стандартное я допилить не могу, то я просто не будут использовать этот стандарт и будут искать что-то другое.
Меня всегда удивляет, когда разрабатывают стандарт, но не закладывают каких-то очевидных расширений в него.
Стандарт допускает следующие типы коммитов:
Это не совсем так. Стандарт (текущая версия v1.0.0-beta.2) определяет два особых типа (feat и fix) и отдельно все остальные. Для остальных приведены несколько примеров, но не более того.
Описание коммита не должно закачиваться знаками препинания.
IMHO здраво, но стандарт этого не требует, хотя примеры написаны в этом стиле.
В описание необходимо использовать повелительное наклонение (imperative mood), точно такое же, какое использует сам Git.
IMHO плохая идея, и стандарт этого даже не упоминает. Более того, многие примеры явно не в этом стиле: "feat(lang): added polish language", "fix: minor typos in code"…
Я бы не придирался, если бы Вы сказали, что описанное — это ваше внутреннее соглашение, но ведь Вы поместили все эти пункты под заголовок "Основные тезисы Conventional Commits", что явно не соответствует истине.
Нужно добавить автоматизации и удобства. Для решения этого вопроса нам потребуется два инструмента: генератор коммитов и линтер коммитов, настроенный на проверку перед пушем в репозиторий.
А вот это явно противоречит и духу и букве стандарта. Стандарт рекомендуется применять в момент ручного squash фиче-бранча. Нигде не рекомендуется использовать его для каждого коммита внутри фиче-бранча (и это очень здраво). Не уверен, возможно ли ограничить упомянутые утилиты исключительно этими squashed коммитами в master, но в их использовании нет реальной необходимости если не принуждать разработчиков каждый коммит в их фиче-бранчах оформлять в этом стиле.
Вообще, основная польза этой спецификации не в том, что она задаёт правила оформления коммитов, а в том, что она приводит к линейной истории, состоящей из осмысленных и цельных изменений, которую можно обрабатывать утилитами для автоматизации механических действий вроде подготовки changelog или выбора номера следующей версии для релиза. Иными словами, суть спецификации составляют 4 термина: squash, feat, fix, BREAKING CHANGE — именно они создают ценность. Всё остальное можно поменять, и ничего принципиально не изменится.
Резюмируя: вы молодцы, что внедряете такие стандарты и занимаетесь их популяризацией, но плохо, что вы выдаёте собственный вариант за сторонний стандарт, и ещё хуже, что вы этот сторонний стандарт не до конца поняли перед внедрением.
Лично я против. Это смена контекста. К тому же, возможно, такое, что тикет переоткрывали не раз, и тогда придётся сравнивать время комментариев и коммита.
Джира может быть и недоступна по разным причинам (работаю дома, интернет отвалился, etc).
Ну, а кроме того, убеждён, что человек, пишущий осмысленный текст, чётче начинает понимать, что же он сделал, и, возможно, даже поймёт, что сделал не всё или не так
Зачем придумывать велосипеды? (и да, сквошить все чейнджи в один коммит при PR, чтобы не мусорить в мейне, и нет, имена коммитов в фичабранче не интересуют вообще никого и никогда)
Поддержу коллег выше. Коммит должен иметь форму: номер тикета: название тикета.
Один коммит должен относиться к одному тикету. Если у вас тикеты связаны между собой то линкуйте их в Jira или что там у вас еще. Тикет — единственное место, куда кто-то еще смотрит. Коммит мессадж никто не читает.
Коммит должен иметь форму: номер тикета: название тикета.
Название тикета может не отражать изменений которые были внесены для исправления этого тикета.
Один коммит должен относиться к одному тикету.
Если тикет маленький и локальный — конечно да.
А что делать если тикет большой и по логике разбивается на несколько крупных независимых изменений?
Но нарушают предыдущее Коммит должен иметь форму: номер тикета: название тикета.
Или вы видите смысл в нескольких коммитах с одинаковым комментарием?
И, в реальности, бывает что один коммит может фиксить баги из разных тикетов.
Да, по хорошему, таки тикеты нужно свести в один закрыв остальные как дублирующие.
Но что делать когда каждый тикет описывает свою проблему часть которой фиксит твой коммит?
Если всё строго с форматом, то создать тикет, чётко описывающий что твой коммит частично фиксит в других тикетах и указать общий в сообщении коммита.
Если тикет большой, то сделайте из него epik и разбейте работу на небольшие тикеты.
Здесь важный момент, что если у вас в работе есть система тикетов, то это и есть первичный источник информации. В этом случае в сообщении коммита самое важное — это номер тикета т.к. основная цель, как можно скорее перебросить человека в систему, где хранятся знания.
Если тикетами не пользуетесь, то предложение автора имеет право на существование.
В описанном в статье виде получается часть информации в тикете, а часть в коммите.
Боже, что это за латынь?
trunkbaseddevelopment.com
fix
fix
fix
done
2) если «вливание» — это мерж или типа того, то есть, например, кодревью перед ним при котором ветка стягивается на машину другого разработчика и он может попросить сделать какие-то изменения. Ревью этих изменений в перезаписанной ветке составляет проблему.
3) даже если ведешь разработку оин, но с разных машин, всегда есть риск что-то потерять или испортить при актуализации одной из машин
Вот потому я всегда советую делать squash в отдельном бранче.
Как?
Допустим, у нас есть master, работали мы в feature.
В feature миллион мелких правок, которые нас раздражают и которые мы хотим убрать.
git checkout feature
git merge master
git checkout -b merge_feature
git rebase -i master
Дальше оставляем один или больше коммитов как pick, а все остальные (которые мусор) помечаем как squash. На выходе имеем:
а) Чистую историю для merge'а
б) Грязную историю для истории
в) Минимальные шансы что-то сломать. Сломаем — удаляем бранч merge_feature и делаем заново.
Хуки запускаются до того, как будет введет пароль
А вы как-то правите комментарии при слиянии веток?
Я про вот это сообщение по умолчанию — Merge branch '<merged-branch>' into '<branch>'
P.S. С сообщения к коммитам в представленном репозитории очень толсто получилось.
Тут есть два аспекта: первое — машиночитаемость описания коммита. Всякие фиксированные теги, scope и т.д.
Второе — семантика. Вот о семантике люди как раз и забывают. Семантика — это смысл изменения. Не "что было поменяно" (это видно в диффе), не где было поменяно (это тоже было в диффе), а почему.
При этом есть ещё одна проблема — это контекст. Если я только что потратил час, разбираясь, почему в svg у стрелочек неправильный угол, то мой контекст предельно глубокий (высокий?) — "fix#2 for incorrect calculation of project plane".
Заметим, для человека в том же контексте этот коммит полностью осмысленный. Он даже говорит, что именно было поправлено.
А теперь представьте себе, что это коммит в проект в котором 800к строк и фиксились стрелки в крайне специфичном режиме, о существовании которого и не все разработчики знают?
Таким образом, коммит должен описывать контекст пониже. Объяснить что за стрелочки, в каком режиме и т.д. Частично это может пересекаться с текстом багтрекера (и полностью это переносить не надо). А вот что должно быть абсолютно — это объяснение, почему было сделано так, а не иначе.
Не все коммиты это требуют, но бывают коммиты, в которых текст значит больше, чем код. Например "Use ASCII for progress bar. In a few terminal models (dump & vt100, etc) they can not be rendered and causing distortion. We can't use ncurses here as it is loaded later.".
Вот это "we can't use" — самое ценное в этом коммите.
Вот это "we can't use" — самое ценное в этом коммите.
И именно поэтому оно должно быть написано комментарием непосредственно рядом с кодом, который это реализует — чтобы следующий разработчик нечаянно это не изменил. Или наоборот, изменил, потому что условия тоже изменились, и теперь это можно делать иначе.
Детальное описание коммита — это мета-данные изменения. Их редко читают, а когда читают, то обычно хотят узнать зачем вообще делался этот коммит. Не почему он внёс именно такие изменения, и не какие именно изменения он внёс, а для чего вообще понадобилось данное изменение. Обычно для этого вполне достаточно одной фразы в стиле conventional commit и/или ссылки на issue.
Конкретно в Вашем примере хорошим сообщением коммита было бы: "fix: progress bar rendering for some terminal models".
В общем случае объяснение «почему не» или «почему пришлось так», лучше всего сохранять в описании коммита, а не в комментарии. Потому что комментарий может остаться и при рефакторинге (зачем умный комментарий стирать?), а в коммите он привязан к конкретному изменению.
Примеры:
shopCard.amount/style/mod: #27 outline — изменили стиль аутлайна для инпута суммы на корзине
shopCard/test/add: #28 snapshots — добавлено снапшот-тестирование для корзины
app/build/fix: #29 reduce bundle size
Как генерировать осмысленные коммиты. Применяем стандарт Conventional Commits