Git

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

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

Обрывочное повествование в коде

Представление пулл-реквестов Github “Файлы изменены” сортирует внесенные изменения в алфавитном порядке по имени пути к файлу. Это хорошо для небольших ветвей функциональностей, к чему мы и стремимся, но зачастую случаются комплексные изменения среди взаимозависимых частей, которые неизбежно приводят к большим различиям между несколькими файлами. Ревьюеры могут чувствовать себя обескураженными, глядя на изменения такого типа, отсортированные по алфавиту.

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

Подготовьте четкую историю коммитов

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

Избегайте бесцельных коммитов. Возможно, вы забыли вовремя внести изменения, которые имело смысл логически сгруппировать вместе, и продолжили редактировать файл. Ничего страшного, такое случается сплошь и рядом. Сам факт того, что файл содержит какие-то изменения, не означает, что все эти изменения должны быть зафиксированы в коммитах.

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

Решительно применяйте ребазирование, чтобы избежать создания коммитов с изменениями, которые позже значительно модифицируются или даже удаляются.

Ревьюеру может быть неприятно провести какое-то время в попытке понять, что поменялось в одном коммите, а затем — несколькими коммитами позже — обнаружить, что он по существу потратил свое время на мертвый код. Примените к этим изменениям amend, fixup или squash, прежде чем запрашивать ревью!

Если это звучит слишком хлопотно — что разумно, поскольку git не особо известен своим UX, — я настоятельно рекомендую обдумать использование графического интерфейса Git, с которым многое из этого становится безболезненным.

Запрос код-ревью

После того как вы попросили коллег проверить ваш пулл-реквест, прекратите ребазирование коммитов! Вместо этого передайте через push-изменения, запрошенные ревьюерами, в новые коммиты.

“Но разве это не идет вразрез с целью по сохранению чистой истории коммитов?”

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

Допустим, вы открыли пулл-реквест через эти коммиты:

Псевдо-коммиты для демонстрационных целей (ради простоты использования); на самом деле не стоит нумеровать свои сообщения о коммитах.

Затем ревьюер оставляет комментарий к чему-то, что было связано с изменениями, которые вносит первый коммит. Если вы модифицируете этот коммит и принудительно сделаете push, ваши старые коммиты исчезнут из пулл-реквеста, и все коммиты, начиная с тех, которые были ребазированы, появятся в качестве новых коммитов после этого ревью:

Все коммиты отображаются как новые

Что изменилось с тех пор, как ревьюер в последний раз смотрел на пулл-реквест?
Какие коммиты были модифицированы и поэтому требуют внимания, а какие нет и могут быть пропущены?

Единственный способ сказать это — просмотреть все коммиты, которые были сделаны через принудительный push, и попытаться вспомнить, отличается ли то, что вы видите сейчас, от того, что было раньше.

Если вы попытаетесь нажать на файл, который был прокомментирован, чтобы увидеть, отвечали ли на этот комментарий, или получить больше контекста для кода в окрестностях комментария, вас встретит вот такой очаровательный телескоп:

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

Кроме того, именно так будут выглядеть изменения, если вместо этого вы передадите отдельные новые коммиты:

Можете сказать, что тут нового?

Вам все еще следует ребазировать из ветки master, но до тех пор, пока в коммиты, которые уже были просмотрены, не вносится значимых модификаций. Тогда ревьюерам не нужно будет просматривать их все снова. Рассмотрите возможность после принудительного push добавить комментарий со ссылкой на самый последний просмотренный коммит, чтобы ревьюеры могли продолжить с того места, где остановились.

Изменения одобрены!

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

Я не уверен, вызывает ли сквош-слияние до сих пор споры в 2020 году, но в случае, если все-таки да — им пользуется React.

Если Дэн Абрамов прыгнет с моста, вы тоже так поступите? (Да. Правильный ответ — “да”).

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

Резюмируя:

  • каждый коммит в пулл-реквесте должен рассказывать, что он меняет, и в идеале также то, что мотивировало это изменение;
  • решительно ребазируйте перед открытием пулл-реквеста/слиянием и запросом ревью;
  • после начала ревью прекратите модифицировать коммиты вашей ветки и загружать новые;
  • после одобрения делайте сквош-слияние (или сначала выборочно склейте коммиты, потом сливайте).

Имейте в виду

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

Связанные ресурсы:

Stacked Git — инструмент для управления историями коммитов, который, как я обнаружил, более интуитивно понятен, чем интерактивное ребазирование через интерфейс командной строки. Учебник может выглядеть устрашающе, но это, вероятнее всего, проблема дизайна, когда всё (включая инструкции по использованию Emacs) размещено на одной странице. На самом деле его довольно легко изучить и понемногу пользоваться в дальнейшем.

Читайте также:


Перевод статьи: Chang Wang “How to Optimize Your Pull Requests and Keep Your Code Reviewers Happy”

Предыдущая статья3 простых шага для оптимизации гиперпараметров в любом Python-скрипте
Следующая статьяПрикольные анимации для Flutter-приложений