Дисклеймер. По поводу истории коммитов уже было вылито много воды, в некоторых компаниях есть свои гайды как готовить коммиты, вероятно у многих разработчиков уже были дискуссии с другими по этому поводу.Цель этой заметки - прежде всего зафиксировать мой собственный взгляд на этот вопрос для меня самого.

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

Обычно я стараюсь придерживаться простого правила: один коммит - одно логически целостное изменение. Понятно, что всегда есть допущения и я позволяю себе частные отходы от общего правила. Так, я не всегду буду создавать отдельный коммит ради исправления синтаксической ошибки или минорных правок в коде. Но такое правило служит для меня конечным ориентиром и критерием правильной организации истории изменений.

Пример хорошей истории коммитов:

  1. Подготовка изменений какой то минорный рефакторинг кода, который поможет написать правильные изменения
  2. Разработка тестов тесты не обязательно делать отдельным коммитом, но удобно, если вы практикуете TDD (на этом шаге тесты могут “падать”)
  3. Реализация фичи или исправление ошибки ядро изменений, разработка unit-тестов
  4. Исправления связанные с замечаниями на ревью или тестами

Такая история коммитов помогает сэкономить время на ревью, благодаря тому что большие изменения разбиваются на логически целостные части общей задачи, которыми можно заниматься раздельно. Если одна задача состоит из нескольких логически обособленных подзадач - каждую отдельную подзадачу можно выполнить в виде отдельного коммита. Так, подготовительные действия, которые нужны для основных коммитов я могу вынести в отдельный коммит. Отдельно стоит выделить комментарии к коммитам. Комментарий должен отражать суть изменений, а основная цель - помочь другому разработчику (и себе в будущем) сориентироваться в изменениях. Если вам сложно придумать хороший комментарий для коммита - скорее всего с ним что то не так.

Зачастую во время работы над большой фичей не до конца понятно, как именно будут выглядеть конечные изменения, поэтому реальная история изменений может быть более “богатая”. В этом случае я позволяю себе иногда переписывать собственную историю изменений на ветке так, что бы разбить её на набор небольших связанных изменений. Безусловно, о переписывании истории изменений может идти речь только если с веткой более никто не работает.

Пример плохой истории коммитов для одной задачи:

  1. Добавление моей фичи
  2. исправление
  3. исправление
  4. рефакторинг и исправление структуры данных (в этом коммите также написали тесты)
  5. исправление
  6. исправление вызова метода

Какие проблемы мы здесь видим?

  • Логически целостное изменение размазано по нескольким коммитам.
  • Такую историю изменений можно смотреть только в целом (представьте, что все изменения насчитывают сотни строк).
  • Некоторые коммиты включают в себя несколько задач - приходится “вручную” отделять одни изменения от других.
  • Некоторые исправляют какую то ошибку допущенную ранее - не является логически целостными изменениями.
  • Комментарии к коммитам вроде ‘исправление’ дают слишком мало информации об изменениях.

Итого. Когда вы готовите ваши изменения хорошим тоном будет подумать об истории коммитов, которую вы хотели бы видеть. Может быть так, что в начале работы над задачей история коммитов ещё не до конца понятна. В этом случае кажется разумным переписать историю коммитов после того как задача была выполнена и перед тем как отправить её на ревью.

p.s. Текст этот был подготовлен в сентябре 2019 года, но как то повис в драфтах и конце концов опубликован в мае 2022 года.