Иногда системы контроля версий напоминают групповые чаты: вроде бы все тут собрались по какому-то поводу и пишут о чём-то одном, но что именно пишут ― разобраться порой просто невозможно. Как и в чате, где на одно грамотное и полное сообщение наберётся сотня «гыгы, лол» и «))))))», в Git-коммитах на несколько внятных описаний приходится втрое больше чего-то такого:
c63b59c ЛОГИКА РАБОТЫ File[] filesList; (ВНИМАНИЕ!)
3775079 Правки самые последние NEW
71acc53 Правка последняя
Особенно это становится заметно во времена крупных доработок. Когда у разработчика много задач и горящих дедлайнов, есть соблазн плюнуть на написание нормальных комментариев к коммитам (commit messages) и применить золотое антиправило экономии времени «Разберусь потом». Но когда наступает это «потом», комментарии типа «03.03 – 04.03» или «последняя правка» не дают ничего, кроме чувства досады на себя в прошлом.
В этой статье мы решили напомнить про правила хорошего тона при написании комментариев к коммитам, чтобы позаботиться о себе и своих коллегах.
Напрасная трата времени. Или нет?
Если какая-то фича не работает, самое время проверить, какие изменения выкатили за время её разработки. Всегда хочется чётко понимать, что добавили или убрали, чтобы быстро вернуть к жизни своё творение. Но если вы работаете в большом проекте, то можете даже ни разу не увидеть всех его участников, не говоря уже о том, чтобы спрашивать у них: «А какое изменение ты делал вот тут, Сергей?»
Вы заходите в лог Git и видите следующие коммиты с комментариями:
a0c03f0 СОГЛАСНО док.1
63d7fa2 >еЛиЗаВеТа<
41f9213 2.03-7.03
82318b8 Что-то ЗАГЛЮЧИЛО-исправлено.
56fa988 Правки от Васи
d80e8bc 1.03, внесли вправки
fe70e42 fg.dfdbd - исправлен
Что за «Док.1»? Что делали со второго по седьмое число? Кто такие Вася и Елизавета? Остаётся закатить глаза, как Роберт Дауни-младший в меме, и идти перекапывать все детальные описания и задачи в таск-трекере.
Но в репозитории можно увидеть и другое:
027b50f Сделать отправку состояния с помощью JSON
f885497 Добавить сохранение состояния системы в строку "System"
de542e3 Исправить ошибку с освобождением ресурсов (добавить namesReader.close())
ed3c53f Добавить дополнительный цикл прохода по списку filesList
0047514 Устранить ошибку загрузки из базы данных
b9539fd Изменить логику работы Reader1
Эти комментарии однородные и понятные. Возможно, некоторым из них не хватает детализации, но на уточнение уйдёт буквально пара минут, потому что по описанию уже ясно, где и что искать, а дополнительные пояснения могут находиться в commit body.
Корректный комментарий к коммиту ― это один из способов эффективной коммуникации в команде, которая зачастую является главным пожирателем времени. Даже две полуторачасовые встречи могут отправить разработчика в интеллектуальный нокаут на полдня. А к ним нередко добавляется ситуативное общение по задачам, общение с новичками и тимлидом, специалистами из других отделов. Если при этом приходится по несколько часов в неделю разбираться с непонятными коммитами, вместо сотрудника скоро останутся тлеющие головешки. Написать хороший комментарий ― это способ сэкономить время и себе, и коллегам, позаботиться о них, помочь не нервничать, не выгорать или хотя бы выгорать медленнее.
Если это звучит очевидно, то странно, почему в репозиториях до сих пор часто творится неразбериха. Есть 3 очевидных объяснения:
новички не знают правил;
нет времени писать правильно из-за большой загрузки;
разработчики не хотят соблюдать правила.
В итоге комментарии становятся не помощью, а никому не нужной обязанностью. Из-за того, что они непонятные, ими не пользуются. А чем меньше ими пользуются, тем ниже мотивация что-то менять. Замкнутый круг.
Но в среде разработки гласные или негласные правила есть для всего. Придерживаться одной договорённости проще, чем разбираться с последствиями того, что каждый делает по-своему. Будет лучше, если команда договорится о правилах, касающихся следующих аспектов:
содержания комментария ― указывать ли тип, по какой структуре строятся описания в каждой из ситуаций (например, составлять заголовки по логике «Добавить (что) (куда)» или «Изменить (что) на (что)»), какие слова при этом использовать, в какой форме;
стиля комментария ― как употреблять строчные и прописные буквы, делать ли отступы и переносы, какие знаки препинания можно использовать и т. д.;
метаданных ― как ссылаться на ID задач, указывать ли номер тикета Jira и т. д.
У нас есть свои правила составления описаний для коммитов, однако они не являются чем-то уникальным и секретным. Они коррелируются с тем, о чём рассказывает Крис Бимс в своей статье и на GIT Hub и чего так или иначе придерживаются тысячи разработчиков по всему миру. Расскажем о них подробнее и с примерами.
8 правил описаний для коммитов
Правило 1: добавлять ID задачи
Распространённая практика ― добавление ID задачи в Jira или другом трекере задач перед описанием. Это нужно, чтобы быстро перейти к контексту изменения и узнать его детали. Или, наоборот, для того, чтобы быстро найти в Git изменения, относящиеся к конкретной задаче.
Правило 2: писать заголовки до 50 символов
Заголовок ― это очень краткое описание всех изменений, которое первым видит разработчик в инструменте контроля версий. Его оптимальная длина ― до 50 символов. На практике он может быть и длиннее (GitHub оповещает, что объём фразы больше, но разрешает её продолжить). Сокращение заголовка действительно полезно со следующих точек зрения:
именно такой формат проще всего воспринимается при беглом изучении репозитория, позволяет быстро понять суть изменений;
заставляет авторов как можно чётче формулировать свои мысли. В первое время это может раздражать, но через пару недель краткие и ёмкие формулировки начинают будто сами рождаться в мыслях, мы проверяли.
Заголовок должен быть не только коротким, но и самодостаточным. То есть по возможности содержать фактическую информацию об изменении. Например, можно написать «Создать Python3-правило сборки status.py», и это будет нести исчерпывающий смысл. Но если написать «Создать новое правило сборки», коллеги, скорее всего, просто не станут разбираться и забьют.
Соблазн написать длинный заголовок возникает тогда, когда вы фиксируете сразу много изменений. На этот случай придумали понятие «атомарные коммиты». Это принцип, по которому фиксировать следует каждое частное завершённое изменение отдельно. Это работает, даже когда вы уже ранее закоммитили «пакет» из нескольких доработок. Если в него требуется внести изменения, лучше создать для каждого из них отдельный коммит. Если что-то будет работать не так, не придётся снова откатывать весь «пакет», достаточно будет откатить, например, только последующую корректировку цвета.
Кроме того, лучше отказаться от принципа фиксации версии только в какое-то определённое время (например, в конце рабочего дня). У каждого коммита должна быть логика: конкретное завершённое изменение или несколько изменений. Также мы обычно фиксируем рефакторинг отдельно от изменений функций или от корректировки ошибок. Например, перемещение класса выполняется одним коммитом, а корректировка ошибки в классе ― другим. Так намного легче искать и понимать изменения.
Правило 3: делать отступ между заголовком и описанием
Заголовок не только сразу отражает суть изменений в репозитории. Он может использоваться и в других полезных процессах. Например, он может стать темой email при использовании команды git-format-patch. Далее лучше оставлять пустую строку, а ниже размещать более детальное описание, например, указать на причины изменений, если они важны для проекта.
Не каждый коммит требует описания. Если изменения незначительны или не влияют на дальнейшую работу с проектом, то дополнительную информацию можно не вносить.
Например, можно написать просто:
Метод Divider изменить на тип void
А дальше, чтобы получить подробную информацию о том, что именно исправили, любой желающий может воспользоваться командами:
git diff ― отображение изменённого файла в консоли с детализацией изменений;
git show ID ― отображение изменений конкретного коммита;
git log -p ― отображение всех коммитов от новых к старым с изменениями в файлах.
Если причины изменений критически важны для проекта и могут быть полезны другим разработчикам (например, влиять на дальнейшие действия в проекте), то их следует указать.
Например:
Метод Divider изменить на тип void
Так как класс employee после последних кадровых изменений стал однородным, он не требует разной обработки в зависимости от условий. Поэтому было убрано возвращаемое значение.
Детальное описание удобно выполнять в редакторе, однако его можно оставить и в строке выполнения команды, добавляя к git commit ключ -m.
Отделение заголовка от описания позволяет быстрее визуально ориентироваться в информации.
Вот пример полной записи в журнале:
$ git log
commit facdd14e2a56e5efbba424b0941ac2501da26be8 (HEAD -> master)
Author: DanMiller <DanM@exitt.com>
Date: Tue Mar 15 22:30:16 2022 +0300
Метод Divider изменить на тип void
Так как класс employee после последних кадровых изменений стал однородным, он не требует разной обработки в зависимости от условий. Поэтому было убрано возвращаемое значение.
Если вывести только основную информацию о коммите с помощью команды git log --oneline, получим:
$ git log --oneline
facdd14 (HEAD -> master) Метод Divider изменить на тип void
Правило 4: писать заголовок с заглавной буквы
И в русском, и в английском языках начало предложения отмечается заглавной буквой, поэтому глаз быстрее и проще распознаёт такую фразу.
Пример:
f885497 Подключить к базе данных
b9539fd Устранить ошибку загрузки из базы данных
027b50f Сделать отправку состояния с помощью JSON
Написание со строчной буквы может помешать быстрому распознаванию текста. Кроме того, многих это просто раздражает, потому что выглядит неаккуратно.
Правило 5: не ставить точку в конце заголовка описания
Знаки препинания в заголовке обычно не нужны, кроме случаев, когда они помогают раскрывать смысл. Например, заключение слова в скобки может быть необходимо для конкретизации предыдущих фраз в заголовке:
Исправить ошибку с освобождением ресурсов (добавлять namesReader.close())
Точка же не выполняет значимых функций в заголовке, потому что он обычно состоит только из одного предложения.
Неправильно:
Загрузить начальную конфигурацию.
Правильно:
Загрузить начальную конфигурацию
В целом лишних знаков препинания лучше избегать, чтобы уложиться в минимальное количество символов.
Правило 6: использовать в заголовке глагол в форме инфинитива
В английском оригинале это правило звучит как «Используйте глагол в повелительном наклонении», но для русского языка оно не очень подходит. Повелительное наклонение в русском ― это слова типа напиши, сходи, принеси и т. д. В английском же повелительное наклонение ― это форма инфинитива без частицы to. Мы предполагаем, что в английском такую форму рекомендуют использовать просто для краткости, ведь слова в изъявительном наклонении там имеют окончания, которые увеличивают количество символов: fixed вместо fix, consolidating вместо consolidate и т. д.
Таким образом, для русскоязычных коммитов больше подходят глаголы в форме инфинитива. Они не сильно короче, чем глаголы в изъявительном наклонении или отглагольные существительные (типа загрузка, обработка и пр.), однако выглядят нейтрально, единообразно и прямо называют произведённое действие.
Заголовок должен быть похож на команду или инструкцию:
Оповестить slave-устройства
Загрузить начальную конфигурацию
Подписаться на топики
Обработать сырую базу значений
Исправить ошибку загрузки из БД
В изъявительном наклонении и с существительными это бы выглядело так:
Настроили оповещение slave-устройств
Загрузка начальной конфигурации
Подписка на топики
Обработка сырой базы значений
Исправили ошибку загрузки из БД
Выглядит разнородно и не очень удобно читается.
Чтобы запомнить это правило и не сбиваться, можно использовать следующий принцип. Заголовок должен логично с точки зрения смысла продолжать фразу «При применении коммит будет...». Вид глагола при этом может измениться.
Например:
При применении коммит будет оповещать slave-устройства
... будет загружать начальную конфигурацию
... будет подписываться на топики
... будет обрабатывать сырую базу значений... будет исправлять ошибку загрузки из БД
Конечно, если хочется пользоваться всеми возможностями богатого русского языка и писать в прошедшем времени (исправил, изменила, устранил и т. д.) или в повелительном наклонении (создайте, добавьте и т. д.), то вполне можно это делать. Главное ― договориться об этом с командой и делать единообразно.
В теле описания можно использовать любые слова и словоформы.
Правило 7: ограничивать длину строки в теле описания 72 символами
Тело описания коммита не переносится в GIT автоматически, это выглядит как убегающая далеко за пределы экрана вправо строка, которую неудобно читать.
Поэтому перенос лучше делать вручную, оставляя на строке 72 символа или менее. Это число неслучайно. Отраслевой стандарт удобочитаемости одной строки ― 80 символов. Однако Git добавляет отступ слева, чтобы описание коммита визуально выделялось, и этот отступ тоже представляет собой символы.
Правило 8: в теле описания должны быть ответы на вопросы: «Что?» и «Почему?»
Про форму достаточно, пришло время поговорить про содержание. По описанию другой специалист, который будет работать с репозиторием, должен понимать контекст изменений. В нём может содержаться информация о важных ограничениях в работе.
В следующем примере разработчик не поленился объяснить, почему были произведены изменения и в чём конкретно они заключались:
commit facdd14e2a56e5efbba424b0941ac2501da26be8 (HEAD -> master)
Author: DanMiller <DanM@exitt.com>
Date: Tue Mar 15 22:30:16 2022 +0300
Ввести возможность подписки на систему топиков
Предыдущая версия прошивки не позволяла в полной мере работать с системой топиков из-за возникавших ошибок, поэтому было проделано следующее.
Так как библиотека PubSubClient.h хочет принимать на вход только массив символов (char), был проработан метод autoBuilder() для создания отдельных строк с названиями топиков, чтобы далее, при назначении переменных (#define), вызывать у этих строк функцию c_str() для перевода в массив символов.
Но не все герои носят плащи.
Есть ситуации, когда отвечать на вопрос «Что?» нерационально. Например, если код сложный, то описывать его в commit messages ― это как писать краткое содержание «Войны и мира» (долго, утомительно и бессмысленно). Можно разъяснить сложные моменты в комментариях к коду, а в описании к коммиту изложить, как всё работало до изменений и как стало после.
Итак, подведём итоги. Корректные и единообразные описания для коммитов важны с двух точек зрения:
их можно удобно и быстро найти и прочитать;
они дают максимально возможное количество информации об изменении с использованием минимального количества знаков.
И поскольку время ― один из самых ценных ресурсов в современном мире, его экономия для себя и своих коллег ― это отличный способ проявить заботу.
Для того чтобы описания были корректными, мы рекомендуем соблюдать восемь правил:
добавлять ID задачи;
писать короткие заголовки ― до 50 символов;
делать отступ между заголовком и описанием;
писать заголовок с заглавной буквы;
не ставить точку в конце заголовка описания;
использовать в заголовке глагол в форме инфинитива;
ограничивать длину строки в теле описания 72 символами;
в теле описания отвечать на вопросы: «Что сделали?» и «Почему сделали?»
Что вы думаете об этих правилах и как сами пишете описания?