Изучаем Git. Урок 24.
Мердж-реквесты и код-ревью
Видеоурок
Конспект урока
Краткое содержание урока, основные инструкции для командной строки, полезные ссылки и советы.
Что такое мердж-реквест?
Зачем нужны мердж-реквесты?
В первую очередь они нужны при работе в команде для проведения код-ревью. Чтобы коллеги увидели новый код и как минимум его просмотрели и оставили замечания или вопросы
Как правильно: merge request или pull request?
Как проходит процедура мердж-реквеста
Немного о markdown
Markdown позволяет форматировать текст: задавать заголовки, списки, цитаты, вставлять ссылки и картинки и даже форматировать код. Насчет кода, возможно, для приграммиста это самая удобная фишка markdown, так как используется достаточно часто
Изучается markdown быстро, разметка очень простая. Вот пример оформления списка, используются звездочки
А вот пример оформления кода, используются апострофы
После этого ваш текст красиво отформатируется, можете попробовать в любом markdown онлайн-редакторе, например, dillinger.io/
Совет от автора
Немного о код ревью
Это отдельная большая тема и git она не касается. Поэтому приведу только кратко причины проводить код ревью
Вопросы на код ревью могут быть совершенно разные и на разные темы. Это всего лишь краткий перечень плюсов от код ревью
Как оповестить коллег о новом мердж-реквесте
Здесь разные варианты, зависит от договоренностей в команде.
Главное договориться как будет удобнее всем в вашей команде
Кто принимает мердж-реквесты
Здесь тоже могут быть разные варианты:
Немного о работе в команде
Request response diagram: что такое и зачем это нужно
Мы продолжаем серию публикаций об артефактах, которые клиенты получают на самой первом этапе разработки — дискавери фазы. Мы уже объяснили, что такое MindMap, Пользовательские истории, BPMN-диаграмма, Customer Journey Map и как мы используем эти инструменты в разработке. Сегодня говорим о Request response diagram — этот артефакт необязательный, мы его используем, если в проекте предусмотрены интеграции (например, с Google-переводчиком, сервисом доставки и логистики, онлайн-оплатой и т. д.).
Request response diagram или диаграмма последовательности — разновидность диаграмм взаимодействия. Обычно она содержит объекты, которые взаимодействуют в рамках сценария, сообщения, которыми они обмениваются, и возвращаемые результаты, связанные с сообщениями. Диаграммы последовательностей используются для более детального описания логики сценариев использования.
Request response diagram отражает:
В отличие от BPMN-диаграммы, которая показывает алгоритм работы системы, Request response diagram обращают внимание разработчиков на сообщениях, которыми объекты обмениваются друг с другом.
Разберем на простом примере, как работает Request response diagram, чтобы наглядно представить, как работает этот артефакт. Эта диаграмма отображает обслуживание в ресторане:
Фред (клиент) заказывает еду Бобу (официанту), Боб передает заказ Хэнку (повару). Пока повар готовит еду, официант наливает вино клиенту. Хэнк отдает заказ Бобу, Боб сервирует блюда. Фред ест и потом рассчитывается за ужин через кассира Ренне.
Это простая схема, в веб и мобильной разработке на таких диаграммах отображаются более сложные процессы и интеграции. Но такой инструмент дает понимание логики процесса, так как мы видим как должны работать объекты на протяжении всего временного цикла. Request response diagram — довольно сложная нотация, которая имеет свой язык. Чтобы правильно прочитать ее, необходимо знать значение каждого символа. Останавливаться на расшифровке мы сейчас не будем, так как клиентам студии обычно не приходится разбираться с диаграммой, этот артефакт скорее оптимизирует работу в команде разработчиков.
Request response diagram чаще всего применяются на этапе дискавери фазы, когда у сервиса есть интеграция.
Есть интеграция — есть необходимость прописать логику с этой интеграцией.Эта логика заключается не только в том, чтобы показать запросы и ответы самой системы, но и в экономии средств клиента, в случае если интеграция платная.
Бизнес или системные аналитики в компании с проджект-менеджером разрабатывают бизнес-модель, которая позволит сделать продуктивную и экономичную интеграцию. На примере интеграции с google-переводчиком (на схеме ниже) видно, что эта диаграмма показывает, как сохранить все переведенные ранее тексты в систему, чтобы пользоваться ими в будущем. Тем самым не придется каждый раз обращаться к платному переводчику и тратить деньги клиента.
После дискавери фазы, имея на руках проработанную интеграцию, разработчик понимает, каким образом она должна работать. В этом случае он может дать оценку по времени и соответственно стоимости разработки. Приступая к работе, разработчик тратит гораздо меньше времени, чтобы реализовать интеграцию. Клиент получает результат интеграции с системой в более короткий срок.
Поэтому мы всегда рекомендуем делать диаграмму на этапе дискавери (но только тогда, когда это действительно нужно проекту). Однако решение всегда остается за заказчиком.
Pull request’ы на GitHub или Как мне внести изменения в чужой проект
По просьбе tulskiy делаю вольный перевод частей официальной документации GitHub’а Fork A Repo и Send pull requests.
Итак, что же такое «запрос на включение (сделанных вами изменений)» (именно так я перевёл pull request)? В официальной документации гитхаба говорится следующее:
Pull request’ы позволяют вам рассказать другим о тех изменениях, которые вы разместили в своём GitHub-репозитории. Как только pull request отправлен, заинтересованные стороны рассматривают ваши изменения, обсуждают возможные правки или даже добавляют дополняющие коммиты, если нужно.
Немного о моделях совместной разработки
Делаем копию репозитория
Рассматривая первую модель разработки, необходимо иметь свою копию изначального репозитория, в которой и будет вестись работа, и изменения из которой и будут предлагаться затем автору изначального репозитория.
В рамках руководства, будем считать, что мы работаем над репозиторием Spoon-Knife пользователя octocat, а ваше имя пользователя — username.
Сделать это очень просто: на странице репозитория имеется кнопочка «Fork», которую и следует нажать.
После чего, эту свою копию уже можно «стянуть» на свой компьютер:
Склонированный репозиторий имеет одну привязку к удалённому репозиторию, названную origin, которая указывает на вашу копию на GitHub, а не на оригинальный репозиторий, чтобы отслеживать изменения и в нём, вам нужно будет добавить другую привязку, названную, например, upstream.
Делаем работу
Итак, в этой точке мы уже можем править код и делать коммиты. Если вы сделали все предыдущие шаги, чтобы потом вернуть ваши изменения в оригинальный репозиторий, то я настоятельно советую делать всю работу в отдельной тематической ветви разработки. Полезность этого станет ясна на этапе посылки pull request’а. Пускай она будет называться feature.
Вот, теперь творите добро (и пусть оно будет выражаться в коммитах).
Как только вы сделали работу (или её часть), отправьте её в свою копию репозитория на GitHub:
Возвращаем изменения: Pull request
Итак, всё сделано. Вы написали код, он у вас в ветви feature как у вас на компьютере, так и на GitHub’е. Осталось только «заслать» его в оригинальный репозиторий.
Идите на страницу вашей копии репозитория на GitHub, выбирайте ветвь feature и жмите кнопку Pull Request.
Далее вы попадёте на предпросмотровую страницу, на которой сможете ввести название и описание ваших изменений (название потом попадёт в описание мёрдж-коммита и станет достоянием общественности, учтите это).
Там же вы можете посмотреть, какие коммиты попали в пулл реквест:
А так же общий diff всех изменений в пулл реквесте:
По умолчанию, пулл реквесты считаются основанными на самой часто интегрируемой ветви родительского репозитория. В этом случае username/Spoon-Knife был скопирован с octocat/Spoon-Knife, так что pull request считается основанным на ветке master репозитория octocat/Spoon-Knife. В большинстве случаев, это будет корректно, но если не так, то вы можете нажать на кнопку «Change Commits»
Вы попадёте в форму выбора базовой и исходной ветвей:
Слева выбираете в какую ветку будут вливаться изменения в родительском репозитории, справа — какие изменения будут браться с вашего репозитория. По примеру: справа octocat/Spoon-Knife/master, слева username/Spoon-Knife/feature. Здесь вы можете указывать не только ветки, но так же теги и id отдельных коммитов в соответствующем репозитории.
ВАЖНО: Договоритесь с владельцем «родительского» репозитория, в какую ветку будете вливать изменения (он может написать это в README)
Изменение базового репозитория меняет и список людей, кто получит уведомление о пулл реквесте. Каждый, кто имеет право «на запись» в базовый репозиторий, получит письмо и увидит уведомление на главной GitHub’а, в следующий раз, как на него зайдёт.
Как только список коммитов вас удовлетворит, нажмите кнопку Update Commit Range.
Когда вы ввели название и описание и перепроверили список коммитов и изменения в файлы, попавшие в пулл реквест, нажмите кнопку Send pull request. Пулл реквест будет создан незамедлительно.
Что дальше?
Следите за вашим пулл-реквестом. Что прокомментируют люди, что скажет мэйнтэйнер, примет или нет ваш пулл реквест.
Когда ваш pull request примут, не забудьте слить изменения в свой репозиторий (или удалить его, если больше не нужен):
Так же можно удалить ветку, в которой велась разработка:
Что следует делать, если работа заняла большое время и оригинальный репозиторий успел уйти вперёд?
Можно просто влить изменения из оригинального репозитория к себе:
Однако хозяину оригинального репозитория или, может быть, даже вам, не понравится наличие мёрж-коммитов и коммитов из master’а в списке коммитов на пулл. В таком случае вам стоит воспользоваться git rebase.
Прочитать про то, как работает rebase можно в официальном руководстве. Там имеются и очень понятные иллюстрации. Так же есть статья в помощи GitHub.
ВНИМАНИЕ: Пожалуйста, учтите, что git rebase меняет id коммитов! Поэтому, все действия с этой командой стоит выполнять только на локальном репозитории, до того, как эти коммиты станут общедоступны, т.е. до того, как вы их push’нули на гитхаб.
Если вы хозяин: Как принять pull request
Если пулл реквест удовлетворяет всем условиям, то кто-либо с правом «на запись» (т.е. может сделать push) в целевой репозиторий, должен принять pull request одним из многих методов. Ниже описаны три наиболее популярных метода:
Auto Merge (автослияние)
Во многих случаях можно попросить github автоматически принять пулл реквест, используя большую зелёную кнопку Merge Pull Request, которая сама вольёт изменения, создаст мёрж-коммит и закроет пулл реквест.
Подробнее можно почитать в этом хабратопике: Кнопка слияния на GitHub.
Fetch and Merge (скачать и слить)
Основной метод вливания изменений. Он требует добавления remote, ведущего к репозиторию человека, отправившего pull request, скачивания изменений с этого репозитория, объединения нужной ветви, исправления конфликтов и выгрузки обновлённой ветви обратно в исходный репозиторий:
Patch and Apply (пропатчить и принять)
Предыдущий метод работает хорошо, когда вы работаете в команде или постоянно принимаете изменения от одной и той же группы людей. Другой метод немного быстрее в единичных случаях при использовании git-am.
Закрытие пулл реквеста
Запросы на пулл автоматически закрываются, когда запрошенные коммиты вливаются в репозиторий назначения. При этом генерируется событие, информирующее всех участников разработки, что пулл реквест был принят и влит в основную ветвь.
Так же возможно вручную закрыть пулл реквест в случае, если он был отклонён. Иногда это необходимо в случаях, когда изменения были приняты с помощью git-cherry-pick или другого механизма, который не позволяет обнаружить факт слияния (merge).
Формальная логика “request-response” в изучении английского: преимущества программистов
Я всегда утверждаю, что самые талантливые лингвисты — это программисты. Связано это с их образом мышления, или, если хотите, с некоторой профессиональной деформацией.
Для раскрытия темы приведу несколько историй из жизни. Когда в СССР был дефицит, а мой муж был маленьким мальчиком, его родители где-то достали колбасу и подали на стол на праздник. Гости ушли, мальчик посмотрел на оставшуюся на столе колбасу, нарезанную аккуратными кружками, и спросил, нужна ли она ещё. “Бери бери!” — разрешили родители. Ну, он взял, пошел во двор, и стал с помощью колбасы учить соседских кошек ходить на задних лапках. Папа с мамой увидели и возмутились разбазариванием дефицитного продукта. А мальчик недоумевал, и даже обиделся. Ведь он же не втихушку стащил, а честно спросил, нужна ли еще колбаса…
Нет нужды говорить, что этот мальчик, когда вырос, стал программистом.
К зрелому возрасту таких забавных историй у айтишника накопилось множество. Например, однажды я попросила мужа купить курицу. Покрупнее и побелее по цвету чтобы птичка была. Он с гордостью принес домой огромную белую… утку. Я спросила, неужели он хотя бы по цене (утка стоит гораздо дороже) не задумался, ту ли птицу он покупает? Ответом мне было: “Ну, ты же о цене ничего не говорила. Сказала, птичку покрупнее и побелее. Я и выбрал из всего ассортимента самую крупную и самую белую ощипанную птицу! Задачу выполнил.” Я облегченно выдохнула, поблагодарив про себя небеса за то, что в магазине в тот день не было индейки. В общем, на ужин была утка.
Ну, и масса других ситуаций, в которых человек неподготовленный может заподозрить жесткий троллинг и даже обидеться. Гуляем по восхитительному южному пляжу, я мечтательно говорю: “Эх, так хочется чего-нибудь вкусненького…” Он, оглядевшись, заботливо спрашивает: “Хочешь, нарву плодов кактуса?”
Я надулась, едко поинтересовавшись, не пришло ли ему случайно в голову сводить меня в уютное кафе с пирожными, например. Муж ответил, что кафе в округе не увидел, а вот плоды опунции, которые он заметил в зарослях кактуса, очень даже вкусны, и вполне могут удовлетворить мой запрос. Логично.
Обижаться? Обнять и простить? Посмеяться?
Данную особенность профессионального мышления, порой провоцирующую курьезы в быту, айтишники могут поставить себе на службу в нелегком деле изучения английского.
Проиллюстрированный выше способ мышления (не будучи психологом, рискну условно охарактеризовать его как формально-логический),
а) резонирует с некоторыми принципами работы человеческого подсознания;
б) как нельзя лучше резонирует с некоторыми аспектами грамматической логики английского.
Особенности подсознательного восприятия запроса
Психология считает, что человеческое подсознание понимает все буквально и не обладает чувством юмора. Как и компьютер, с которым айтишник “общается” больше времени, чем с людьми. Подслушала у одного практикующего психолога метафору: “Подсознание — это великан, у которого нет глаз, нет чувства юмора, и который всё понимает буквально. А сознание — это зрячий лилипут, который сидит на шее великана и им управляет.”
Какая команда считывается великаном-подсознанием, когда лилипут-сознание произносит: “Мне нужно изучить английский”? Подсознание принимает REQUEST: “изучить английский”. Простодушный “великан” усердно начинает работать над выполнением команды, выдавая RESPONSE: процесс изучения. Вы узнаете, что в английском есть герундий, есть глагол to be, есть активный залог, есть пассивный залог, есть видовременные формы, есть сложное дополнение и сослагательное наклонение, есть актуальное членение, есть синтагмы, и т.д.
Изучали ли вы язык? Да. “Великан” выполнил поставленную задачу — вы честно изучали язык. Овладели ли вы английским на практике? Вряд ли. Запроса на овладение подсознание не получало.
Чем же различается изучение и овладение?
Изучение — это анализ, расчленение целого на части. Овладение — это синтез, сборка частей в целое. Подходы, прямо скажем, противоположные. Методики у изучения и у практического овладения разные.
Если конечная цель — научиться пользоваться языком как инструментом, то и формулировать задачу следует буквально: “Мне нужно овладеть английским.” Будет меньше разочарований.
Каков request, таков и response
Как упоминалось выше, английскому языку присущ некий формализм. К примеру, на поставленный вопрос нельзя в английском ответить как угодно. Можно ответить лишь в той форме, в которой он задан. Таким образом, на вопрос “Have you eaten the cake?” можно ответить лишь в той же грамматической форме с have: “Yes, I have / No, I haven’t.” Никаких “do” или “am”. Точно так же, на “Did you eat the cake?” правильно будет ответить “Yes, I did / No, I didn’t.”, и никаких “had” или “was”. Каков вопрос, таков ответ.
У русскоязычных часто вызывает недоумение момент, когда в английском, чтобы разрешить что-то, необходимо ответить отрицательно, а чтобы запретить, — положительно. Например:
Ведь естественный инстинкт русскоязычного сознания — разрешая, ответить “да”, а запрещая, — “нет”. Почему же в английском все наоборот?
Формальная логика. Отвечая на вопрос в английском, мы откликаемся не столько на реальную ситуацию, сколько на грамматику предложения, которое слышим. А в грамматике у нас вопрос звучит: “Do you mind?” — “Возражаете ли Вы?”. Соответственно, отвечая “Yes, I do.” — собеседник, откликаясь на грамматическую логику, утверждает “Да, возражаю”, т.е., запрещает, а вовсе не разрешает действие, как было бы логично для ситуативной логики. Каков вопрос, таков и ответ.
Аналогичное столкновение ситуативной и грамматической логики провоцируют просьбы типа “Could you…?” Не удивляйтесь, если в ответ на Ваше:
… и спокойно продолжит свою трапезу, так и не передав вам соль. Вы его спросили, может ли он передать соль. Он ответил, что может. Вы ведь не попросили его передать ее вам: “Would you…?” Носители английского частенько так шутят. Возможно, истоки знаменитого английского юмора кроются как раз на стыке противоречия грамматической и ситуативной логики… Совсем как юмор программистов, не находите?
Таким образом, приступая к освоению английского, имеет смысл пересмотреть формулировку запроса. Ведь когда мы приходим, например, в автошколу, мы говорим: “Мне нужно научиться водить автомобиль”, а не “Мне нужно изучить автомобиль”.
Более того, работая с преподавателем, студент вступает во взаимодействие с его когнитивной системой. У преподавателя тоже есть подсознание, работающее, как у всех людей, по принципу “request-response”. Если преподаватель не настолько опытный, чтобы “переводить” запрос обучаемого на язык его реальных потребностей, подсознание преподавателя также может воспринять запрос ученика как запрос на изучение, а не на овладение. И преподаватель с энтузиазмом откликнется и удовлетворит запрос, но предложенная к изучению информация не будет являться реализацией истинной потребности студента.
“Бойтесь своих желаний” (С)? Ищите преподавателя-телепата, умеющего переводить ваши запросы на язык ваших реальных потребностей? Корректно формулируйте ‘request’? Необходимое подчеркнуть. При грамотном подходе к делу, лучше всех обучающихся английским должны владеть именно программисты, как из-за особенностей их мировосприятия, так и из-за особенностей английского языка как такового. Залог успеха — правильный подход.
Что такое пул-реквесты и зачем они нужны?
Перевод статьи «What’s the Point of Pull Requests Anyway?»
Если вы еще новичок в мире Git и тесно связанных с ним платформ (например, GitHub или GitLab), то вы могли и не слышать таких терминов, как пул-реквест (pull request) или мерж-реквест (merge request). И даже если что-то такое слышали, то можете не знать, что означают эти термины и зачем нужны эти самые «реквесты».
Примечание. В статье я буду использовать термин «пул-реквест», но по сути это то же самое, что мерж-реквест, только последний используется на GitLab.
Пул-реквесты помогают командам создавать программы и распространять их. Чтобы вникнуть в саму идею, придется немного напрячься, но я уверен, что дело того стоит. Моя цель — помочь вам познакомиться с пул-реквестами и рассказать, какое место они занимают в процессе разработки ПО.
Что такое пул-реквест?
Пул-реквест это запрос (англ. request — «запрос») на интеграцию изменений из одной ветки в другую. Причем в ветке может быть всего один коммит одного разработчика, а может быть несколько коммитов разных авторов. В большинстве случаев пул-реквест используется для интеграции нового функционала или для исправления бага в основной ветке проекта.
Пул-реквест также содержит короткое описание изменений и причин, по которым эти изменения вносятся. Обычно между автором пул-реквеста и ревьюерами происходит обсуждение этих изменений.
Ревьюеры — это другие разработчики, работающие над этим проектом и способные дать обратную связь по вносимым изменениям. В проектах с открытым исходным кодом в роли ревьюеров обычно выступают ключевые контрибьюторы или мейнтейнеры. В других случаях (например, в вашей команде на работе) ревьюерами бывают более опытные коллеги (разработчики-сеньоры).
Вот как выглядит пул-реквест с простым описанием и ссылкой на issue (проблему) на GitHub:
Теперь, когда мы дали определение пул-реквестам, давайте посмотрим, почему они столь популярны и чем могут быть полезны.
Коммуникация
По сути пул-реквесты облегчают процесс совместной работы с другими людьми. Они позволяют сделать прозрачной коммуникацию между авторами и ревьюерами путем показа дифф-ов (diffs), коммитов (commits) и комментариев, поясняющих изменения.
До пул-реквестов изменения подтверждались по электронной почте или в IRC-каналах. Там писали название ветки или указывали набор коммитов. Чтобы смержить (слить) изменения, мейнтейнер или выпускающий разработчик должен был сравнить изменения с текущей версией кода на собственном компьютере, дать фидбэк, а потом подождать ответа с дополнительными изменениями. Согласованные изменения мержил на своей локальной машине, а затем отправлял их в общую кодовую базу. Пул-реквесты существенно упрощают весь этот процесс.
Особенно это касается крупных проектов, над которыми работают тысячи контрибьюторов. Поэтому многие из подобных проектов придерживаются именно процедуры пул-реквестов. Часто они также применяют рабочий процесс под названием «GitHub flow». GitHub flow предполагает форки целых проектов и создание пул-реквестов в этих форках.
Поначалу все это кажется страшным и непонятным, но не волнуйтесь! Просто помните, что основная идея остается прежней: вы запрашиваете разрешение на перенос изменений из одной ветки в другую.
Еще одно преимущество процедуры пул-реквестов в том, что всем сотрудникам видна вся коммуникация по изменениям. К вашим услугам поиск по внесенным изменениям и возможность использовать теги. В общем, отслеживать происходящее относительно легко. Контекст и предыдущие решения не теряются где-то в потоках электронных писем или окнах чатов. Любой разработчик, участвующий в проекте, может легко найти и просмотреть нужные сведения.
Автоматизация
Поскольку пул-реквесты приобрели огромную популярность в сообществе разработчиков, GitHub и другие подобные платформы создали обширный набор вебхуков (webhooks), спроектированных на основе GitHub flow. Эти вебхуки делают возможной автоматизацию работы. В наши дни распространена практика, когда задачи непрерывной интеграции выполняются при каждом коммите, и поэтому являются частью пул-реквеста. По своему опыту могу судить, что это одно из самых подходящих мест для автоматизации. Речь идет не только о запуске автоматизированных тестов. Из изменений в пул-реквесте можно разворачивать целые окружения, чтобы проверить, гладко ли все прошло.
Раньше подобные инструменты интеграции были дорогими. Команде или приходилось поддерживать инфраструктуру для задач автоматизации, либо платить за сервисы. В последнее время все больше инструментов становятся доступными, а значит, настройка автоматизированных задач облегчается. Например, вы можете воспользоваться бесплатными предложениями таких компаний как Netlify и Travis.
GitHub пошел даже еще дальше и выпустил GitHub Actions. Actions позволяют вам создавать рабочие процессы автоматизации из набора отдельных маленьких задач, пригодных для компоновки. Непременно попробуйте!
Проверки статуса
Последнее большое преимущество пул-реквестов это концепция проверок статуса (status checks). Проверки статуса это просто набор задач, выполняемых для каждого коммита в пул-реквесте, и выдающих результат «успех» (success) или «провал» (failure). Это буквально чек-листы для проверки того, готовы ли изменения к отправке в кодовую базу.
Проверять можно что угодно. В большинстве команд проверки статуса состоят из автоматизированных тестов, за которыми следует проверка стиля, после которой проверяется, получил ли этот код одно или два одобрения на ревью. Изменения не могут быть слиты, пока не пройдут все эти проверки.
Стоит также остановиться на теме код-ревью. Поскольку пул-реквесты сильно улучшают возможности коммуникации и сотрудничества, естественно, что многие команды применят их в код-ревью. Таким образом прямо со страницы пул-реквеста можно осуществлять менеджмент ревьюеров, ревью и статуса запросов (одобрено или нет). Во многих крупных проектах есть даже автоматическая процедура добавления отдельных пользователей или групп к пул-реквесту — в зависимости от файлов, которые были изменены. Если хотите пример, посмотрите документацию CODEOWNERS.
Итоги
Если брать коротко, пул-реквест это просто запрос на внедрение изменений из одной ветки в другую. Несмотря на простоту концепции, пул-реквесты являются очень мощным инструментом. Именно поэтому они стали важной частью современной разработки. Пул-реквесты облегчают задачи непрерывной интеграции, код-ревью и проверки статуса, а все вместе это позволяет поддерживать высокий уровень качества кода.
Если раньше репозиторий был просто местом, где хранится код, то с появлением пул-реквестов он стал местом, где хранятся знания об этом коде.
Также пул-реквесты играют большую роль в процессе обучения. Некоторые из самых важных уроков, касающихся разработки программ, я получил в фидбэках терпеливых ревьюеров моих пул-реквестов.



