Pull to refresh

GitHub Flow: рабочий процесс Гитхаба

Reading time10 min
Views125K
Original author: Scott Chacon
Краткое предисловие переводчика.
Захватывающе интересная статья одного из разработчиков «GitHub Inc.» о принятом в компании рабочем процессе потребовала употребить пару специальных терминов при переводе.

То понятие, для которого на английском языке достаточно одного слóва «workflow», на русский приходится переводить словосочетанием — «рабочий процесс». Ничего лучше не знаю ни сам я, ни при помощи гуглоперевода так что и мне, и читателям придётся с этим мириться, хотя бы и поневоле.

Другое понятие, «deploy», на русский часто переводят словом «развёртывание», но в моём переводе я решил вспомнить оборот из советского делопроизводства — «внедрение инноваций на производстве» — и стану говорить именно о «внедрении» новых фич. Дело в том, что описанный ниже рабочий процесс не имеет «выпусков» (releases), что делает несколько неудобными и речи о каком-либо «развёртывании» их.

К сожалению, некоторые переводчики бывают склонны грубо убивать сочную метафору «иньекции» (или даже «впрыскивания», если угодно), содержающуюся в термине «code injection», так что и его также переводят словосочетанием «внедрение кода». Эта путаница огорчает меня, но ничего не могу поделать. Просто имейте в виду, что здесь «внедрением кода» я стану назвать внедрение его именно в производство (на продакшен), а не в чей-нибудь чужой код.

Я стремился употреблять словосочетание «в Гитхабе» в значении «в компании GitHub Inc.», а «на Гитхабе» — в значении «на сайте GitHub.com». Правда, иногда разделять их сложновато.

Проблемы git-flow


Повсюду путешествую, преподавая Git людям — и почти на каждом уроке и семинаре, недавно мною проведённом, меня спрашивали, что я думаю о git-flow. Я всегда отвечал, что думаю, что этот подход великолепен — он взял систему (Git), для которой могут существовать мириады возможных рабочих процессов, и задокументировал один проверенный и гибкий процесс, который для многих разработчиков годится при довольно простом употреблении. Подход этот также становится чем-то вроде стандарта, так что разработчики могут переходить от проекта к проекту и из компании в компанию, оставаясь знакомыми с этим стандартизированным рабочим процессом.

Однако и у git-flow есть проблемы. Я не раз слыхал мнения людей, выражавших неприязнь к тому, что ветви фич отходят от develop вместо master, или к манере обращения с хотфиксами, но эти проблемы сравнительно невелики.

Для меня одной из более крупных проблем git-flow стала его сложность — бóльшая, чем на самом деле требуется большинству разработчиков и рабочих групп. Его сложность ужé привела к появлению скрипта-помощника для поддержания рабочего процесса. Само по себе это круто, но проблема в том, что помощник работает не из GUI Git, а из командной строки, и получается, что те самые люди, которым необходимо действительно хорошо выучить сложный рабочий процесс, потому что им вручную придётся пройти все шаги его — для этих-то людей система и недостаточно удобна для того, чтобы использовать её из командной строки. Вот что становится крупною проблемою.

Все эти проблемы можно без труда преодолеть, следуя гораздо более простому рабочему процессу. Мы не пользуемся git-flow в Гитхабе. Наш рабочий процесс основан (и всегда был основан) на более простом подходе к Git.

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

Рабочий процесс Гитхаба


Итак, почему мы в Гитхабе не используем git-flow? Главная проблема в том, что у нас принято беспрестанное внедрение изменений. Рабочий процесс git-flow создавался в основном в помощь «выпускам» нового кода. А у нас нет «выпусков», потому что код поступает на продакшен (основной рабочий сервер) ежедневно — иногда по нескольку раз в день. Мы можем подавать для этого команды боту в той же чат-комнате, в которой отображаются итоги CI (интеграционного тестирования). Мы стремимся сделать процесс тестирования кода и его внедрения как можно проще, чтобы каждому сотруднику он был удобен в работе.

У такого частого внедрения новинок есть ряд достоинств. Если оно случается каждые несколько часов, то почти невозможно возникнуть большому количеству крупных багов. Небольшие недочёты случаются, но они могут быть исправлены (а исправления, в свою очередь, внедрены) очень быстро. Обычно пришлось бы делать «хотфикс» или как-то ещё отступать от нормального процесса, но для нас это становится просто частью нормального процесса: в рабочем процессе Гитхаба нет разницы между хотфиксом и небольшою фичею.

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

Как мы это делаем


Итак, каков рабочий процесс Гитхаба?

  • Содержимое ветви master всегда работоспособно (deployable).
     
  • Начиная работу над чем-то новым, ответвляйте от ветви master новую ветвь, имя которой соответствует её предназначению (например, «new-oauth2-scopes»).
     
  • Закоммитив в эту ветвь локально, отправляйте регулярно свою работу и в одноимённую ветвь на сервере.
     
  • Когда вам понадобится отзыв, или помощь, или когда вы сочтёте ветвь готовою ко слиянию, отправьте запрос на слияние.
     
  • После того, как кто-то другой просмотрел и одобрил фичу, вы можете слить вашу ветвь в ветвь master.
     
  • После того, как ветвь master пополнилась новым кодом, вы можете немедленно внедрить его на продакшен и вам следует сделать это.

Вот и весь рабочий процесс. Он очень прост и результативен, он работает для довольно крупных рабочих групп — в Гитхабе сейчас работает 35 человек, из которых, может быть, пятнадцать или двадцать одновременно работают над одним и тем же проектом (github.com). Думаю, что большинство команд разработчиков (групп, одновременно работающих с логикою одного и того же кода, что может порождать конфликты) имеют такой же размер — или меньше такого. Особенно группы, достаточно прогрессивные для того, чтобы заниматься быстрым и последовательным внедрением.

Итак, давайте по порядку рассмотрим каждый шаг.

Содержимое ветви master всегда работоспособно (deployable)


В общем-то это единственное жёсткое правило во всей системе. Есть только одна ветвь, имеющая всегда некоторое особенное значение, и её мы назвали master. Для нас это значит, что код этой ветви либо внедрён на продакшен, либо, в худшем случае, окажется внедрён в течение нескольких часов. Эта ветвь очень редко подвергается откручиванию на несколько коммитов назад (для отмены работы): если возникает проблема, то отменяются изменения из коммитов или совершенно новые коммиты исправляют проблему, но сама ветвь почти никогда назад не откручивается.

Ветвь master стабильна. Внедрение её кода на продакшен или создание новых ветвей на её основе — это всегда, всегда безопасно. Если от вас в master поступает неоттестированный код или он ломает сборку, то вы нарушили «общественный договор» команды разработчиков и у вас на душé должны кошки поскрести по этому поводу. Каждая ветвь подвергается у нас тестированию, а итоги поступают в чат-комнату — так что, если вы не тестировали её локально, то можете запушить ветвь (даже с единственным коммитом) на сервер и подождать, пока Jenkins не сообщит, все ли тесты успешно пройдены.

Ответвляйте от ветви master новые ветви, имена которых соответствуют предназначению


Когда хотите поработать над чем-то новым, ответвляйте от стабильной ветви master новую ветвь, имя которой соответствует предназначению. (Например, в коде Гитхаба прямо сейчас есть ветви «user-content-cache-key», «submodules-init-task», «redis2-transition».) Такое наименование имеет несколько достоинств. Например, достаточно подать команду fetch, чтобы увидеть, над какими темами работают остальные. Кроме того, оставив ветвь на какое-то время и возвратившись к ней позднее, по имени проще припомнить, о чём она была.

И это приятно, потому что, когда на Гитхабе заходим на страницу со списком ветвей, то легко видеть, над какими ветвями недавно поработали (и, приблизительно, каков был объём работы).

[скриншот]

Это почти как список будущих фич с грубою оценкою нынешнего состояния их. Если не пользуетесь этой страницею, то знайте — у ней классные возможности: она вам показывает только те ветви, в которых была проделана работа, уникальная по отношению к выбранной вами в настоящий момент ветви, да ещё и сортирует таким способом, чтобы ветви с наиболее недавнею работою были сверху. Если захочется полюбопытствовать, то я могу нажать на кнопку «Compare» и поглядеть на точный объединённый diff и на список коммитов, уникальных для этой ветви.

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

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


Другое крупное отличие от git-flow: мы беспрерывно делаем push ветвей на сервер. С точки зрения внедрения приходится по-настоящему беспокоиться только о ветви master, так что push никого не озадачит и ничего не поломает: всё, что не master это просто код, над которым идёт работа.

Этим создаётся страховочная копия на случай утраты ноутбука или выхода жёсткого диска из строя. Этим поддерживается, что ещё важнее, постоянный обмен сведениями между разработчиками. Простой командою «git fetch» можно получить список тех TODO, над которыми все сейчас работают.

$ git fetch
remote: Counting objects: 3032, done.
remote: Compressing objects: 100% (947/947), done.
remote: Total 2672 (delta 1993), reused 2328 (delta 1689)
Receiving objects: 100% (2672/2672), 16.45 MiB | 1.04 MiB/s, done.
Resolving deltas: 100% (1993/1993), completed with 213 local objects.
From github.com:github/github
 * [new branch]      charlock-linguist -> origin/charlock-linguist
 * [new branch]      enterprise-non-config -> origin/enterprise-non-config
 * [new branch]      fi-signup  -> origin/fi-signup
   2647a42..4d6d2c2  git-http-server -> origin/git-http-server
 * [new branch]      knyle-style-commits -> origin/knyle-style-commits
   157d2b0..d33e00d  master     -> origin/master
 * [new branch]      menu-behavior-act-i -> origin/menu-behavior-act-i
   ea1c5e2..dfd315a  no-inline-js-config -> origin/no-inline-js-config
 * [new branch]      svg-tests  -> origin/svg-tests
   87bb870..9da23f3  view-modes -> origin/view-modes
 * [new branch]      wild-renaming -> origin/wild-renaming

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

В любое время создавайте запрос на слияние


GitHub снабжён поразительною системою обзора кода, которая называется запросами на слияние; боюсь, недостаточно разработчиков вполне знают о ней. Многие пользуются ею в обыкновенной работе над открытым исходным кодом: форкнул проект, обновил код, отправил запрос на слияние к хозяину проекта. Однако эта система также может употребляться как средство внутрикорпоративной проверки кода, и так её используем мы.

Её мы, собственно, скорее используем как средство просмотра и обсуждения ветвей, чем как запрос на слияние. GitHub поддерживает отсылку запроса на слияние из одной ветви в другую в одном и том же проекте (открытом или приватном), так что в запросе можно сказать «мне нужна подсказка или обзор этого кода», а не только «прошу принять этот код».

[скриншот]

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

[скриншот]

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

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

И это круто, потому что в запросах на слияние можно комментировать отдельные строки объединённого диффа, или отдельные коммиты, или весь запрос в целом — и копии реплик сложатся в единое обсуждение. Также можно продолжать пополнение ветви кодом, так что если кто-нибудь укажет на ошибку или на позабытую возможность в коде, то можно поместить исправление в ту же ветвь, и GitHub покажет новые коммиты в обсуждении, так что и вот так можно трудиться над ветвью.

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

[скриншот]

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

Слияние только после обзора запроса


Мы не работаем непосредственно в ветви master, но и работу из именованной ветви мы не подвергаем слиянию сразу после того, как сочтём её оконченною — сперва мы стараемся получить одобрение от других сотрудников компании. Оно обычно имеет форму «+1», или эмоджи, или комментария «:shipit:», но кого-то ещё нам надо привести поглядеть на ветвь.

[скриншот]

Когда одобрение получено, и ветвь прошла CI, мы можем слить её в master и на внедрение; в этот момент запрос на слияние будет закрыт автоматически.

Внедрение непосредственно после обзора


Наконец, ваш труд окончен, а плоды его — на ветви master. Это означает, что, даже если прямо сейчас вы не станете внедрять их, то они всё равно станут основою для ветвей других сотрудников, и что следующее внедрение (которое, скорее всего, случится через несколько часов) запустит новинку в дело. И так как бывает очень неприятно обнаружить, что кто-то ещё запустил ваш код и пострадал от этого (если код что-то поломал), то людям свойственно самим заботливо проверять стабильность итогов совершённого ими слияния, самостоятельно внедрять результаты.

Наш campfire-бот, по имени hubot, может внедрять код по указанию от любого из сотрудников. Достаточно подать в чате команду hubot deploy github to production, и код поступит на продакшен, где начнётся перезапуск (с нулевым даунтаймом) всех необходимых процессов. Можете сами судить о том, как часто это случается на Гитхабе:

[скриншот]

Как видите, шесть разных человек (среди которых один саппорт и один дизайнер) внедряли код более двух дюжин раз за сутки.

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

Наш рабочий процесс обладает и силою, и невероятною простотою. Думаю, многие согласятся, что GitHub — очень стабильная платформа, что на её проблемы мы реагируем быстро (если они вообще возникают), что новые фичи внедряются в быстром темпе. Там нет таких компромиссов в отношении качества или стабильности, которые могли бы увеличить скорость и простоту рабочего процесса или уменьшить число его шагов.

Заключение


Git сам по себе довольно сложен для понимания. Если его ещё и употреблять в рабочем процессе более сложном, чем это необходимо, то дело кончится ежедневным чрезмерным усилием рассудка. Я всегда буду отстаивать употребление простейшей из возможных систем, пригодных для работы вашей группы, и до тех пор, пока система эта не перестанет работать; только тогда добавляйте сложность, когда никак не удаётся избежать этого.

Для тех рабочих групп, которым необходимо подготавливать официальные выпуски кода через продолжительные интервалы (от нескольких недель до нескольких месяцев между выпусками), и создавать хотфиксы, и ветви поддержки прежних версий, и совершать другие дела, необходимость которых вызывается такими нечастыми выпусками кода, имеет смысл git-flow, и я весьма рекомендовал бы его употребление.

Для групп, труд которых строится вокруг доставки кода, которые ежедневно обновляют продакшен, беспрерывно тестируют и внедряют фичи, я рекомендовал бы более простой рабочий процесс — такой, как GitHub Flow.
Tags:
Hubs:
+99
Comments47

Articles