Во-первых, почему мне это важно
Я работаю над созданием Graphite, источником вдохновения для которого стал внутренний инструментарий Facebook*. Когда я решил создать стартап с друзьями, никогда раньше не слышал о Mercurial, хотя всегда страстно любил инструменты разработчиков. Мой предыдущий опыт разработки включал в себя личные проекты, домашнюю работу в колледже, разработку для iOS в Google и развитие инфраструктуры в Airbnb. На протяжении всей моей карьеры пользование git было таким же естественным, как воздух. Он настолько популярен, что лично я считал его единственным подходящим инструментом для создания изменений в коде и управления ими.
Забавно, что специалист по Mercurial Грегори Сорц работал рядом со мной в Airbnb, хотя я знал его только как приятного коллегу, но не представлял, что он контрибьютор.
В 2021 году мои коллеги по команде Томас и Ник раскрыли мне глаза. Они пришли из Facebook* и, к моему удивлению, едва знали Git. Зато они имели глубокое понимание паттернов Mercurial и рабочего процесса Facebook* на основе «многослойных diff» (stacked diff). Со временем они убедили меня в полезности этого паттерна и мы развернули направление развития компании, чтобы реализовать многослойные diff для разработчиков GitHub.
Но пост посвящён не нашему стартапу. Он о важном вопросе, не дававшем мне покоя последние три года. Почему фейсбукеры не пользуются Git? Зачем они выбрали Mercurial и создали на его основе собственные рабочие процессы? Я знаю, что Google не пользуется Git, но это логично: культура разработки Google возникла на пять лет раньше Git. Facebook* же был основан примерно в то же время, что и создан Git, около 2004 года, и ко времени, когда Facebook* начал серьёзно выбирать инструментарий для управления исходниками, Git был старше и популярнее Mercurial. Так почему же Facebook* не использует Git?
Этот вопрос специфичен и более интересен мне, чем среднестатистическому разработчику, но думаю, будет любопытно над ним поразмыслить. Если бы Facebook* выбрал Git и стал его контрибьютором в начале 2010-х, мир разработки сегодня мог бы выглядеть иначе. Git мог бы быть более удобным для пользователя и нативно поддерживать многослойные изменения. GitHub мог бы разработать более качественную поддержку для разработки ПО с закрытыми исходниками. Компании, основанные рано ушедшими из Facebook* фейсбукерами, наподобие Uber и Pinterest тоже могли бы использовать для управления исходниками Git и GitHub, а не Phabricator и Mercurial, что привело бы к созданию в течение последнего десятилетия менее фрагментированной экосистемы.
Но Facebook* не выбрал Git (для своих основных монорепозиториев). Вместо него он использует для контроля версий Mercurial и инкрементно добавляет поверх него собственный инструментарий. Почему? Для начала я решил загуглить ответ и нашёл следующий подробный пост.
Эта написанная десять лет назад статья, а также более поздние технические обсуждения на YouTube дали мне первоначальный ответ: «из-за производительности».
Но я хотел чего-то более глубокого, мне хотелось услышать мнение инженеров, принявших такое решение. Благодаря помощи коллеги я опубликовал вопрос в группе бывших фейсбукеров. Также я отправил два «холодных» письма двум инженерам, работавшим над проектом по миграции на Mercurial. Они любезно согласились ответить конфиденциально и изложили своё личное мнение о проекте. Вот, что мне удалось узнать о причинах неиспользования Git в Facebook*. Надеюсь, этот пост позволит глубже задокументировать историю того, почему инструменты в 2024 году выглядят именно так.
Мне кажется, в статье недостаточно чётко сказано, что разработчики Mercurial положительно восприняли идею создания инженерами Facebook* патчей для Mercurial с целью более качественного его масштабирования под огромные репозитории, в отличие от разработчиков Git.
Бывший фейсбукер, 2024 год
Почему и как Facebook* мигрировал с Git
Согласно посту Facebook* за 2014 год, компания начинала с Git. Как и можно было ожидать, для компании это был стандартный вариант системы управления исходниками. Но примерно в 2012 году она начала сталкиваться с проблемами ограничения масштабируемости. В посте утверждается, что кодовая база была «во много раз больше даже ядра Linux, состоявшего из 17 миллиона строк и 44 тысяч файлов». В частности, инженеры начали ощущать, что операции Git стали слишком медленными. Не ужасно медленными, но достаточно медленными для того, чтобы приступить к расследованию.
Основным узким местом был процесс «stat-ирования» всех файлов. «Git изучает каждый файл и естественным образом всё больше тормозит с увеличением их количества». Инженеры попробовали запустить симуляцию, создав макет репозитория, соответствующий размеру кодовой базы Facebook* спустя несколько лет. Результат оказался ужасающим — для выполнения простых команд git требовалось более 45 минут. Как сказал работавший над проектом инженер, «это не то, на что можно закрыть глаза, пока не начнут жаловаться все инженеры. К этому моменту всё выйдет из-под контроля. Чтобы придумать более чистое решение, потребовался бы гераклов подвиг».
Поэтому разношёрстная группа разработчиков ПО приступила к изучению возможных решений. Сначала они связались с мейнтейнерами Git, чтобы понять, что потребуется, чтобы расширить Git для улучшения поддержки крупных монорепозиториев:
Вот избранные цитаты из общения с мейнтейнерами Git по почте — прошло уже 12 лет, но я всё равно ощущаю некое раздражение, читая эти письма:
похоже, у вас всё находится в едином .git. Разделите огромный репозиторий на отдельные мелкие репозитории .git.
Хоть это и /можно/ сделать, это плохая идея, вам следует разбить репозитории
Поддерживаю. Я работаю в компании с долгим опытом разработки множества огромных репозиториев CVS, и мы медленно, но уверенно выполняем миграцию кодовой базы с CVS на Git. Разбивайте проекты. Это поможет вам реорганизовать их и, на мой взгляд, не имеет никаких недостатков.
Хотя Git может проявлять себя лучше [sic] с крупными репозиториями (в частности, применение коммитов в интерактивном rebase, похоже, замедляется в случае больших репозиториев), при stat-ировании 1,3 миллиона файлов на большее рассчитывать не приходится.
В этом ответе не видно желания сотрудничать, к тому же сегодня, в будущем, где есть куча крупных монорепозиториев, он выглядит не особо прозорливым. Мейнтейнеры Git отказались от повышения производительности, вместо этого порекомендовав Facebook* разбить его монорепозиторий. Однако шардинг команде Facebook* не подходил; её участники вспоминают, что были удивлены нежеланием расширения возможностей Git. Обычно предложение бесплатного опенсорсного труда крупной технологической компании воспринимается как подарок, способный обеспечить долгую жизнь проектов.
FB*: привет, мейнтейнеры Git, мы хотим, чтобы Git лучше масштабировался под крупные репозитории! Поработаем вместе?
Git: Не-а. Вы делаете всё неправильно. Вам нужна куча мелких репозиториев. Нет причин налаживать работу Git с большими репозиториями, потому что их не должно существовать.
FB*: ...
FB*: Привет, мейнтейнеры Mercurial, мы хотим, чтобы Hg лучше масштабировался под крупные репозитории. Поработаем вместе?
Hg: Отлично! Давайте.
Бывший фейсбукер, 2024 год
Насколько я помню, сообщество Git не было заинтересовано в предложениях FB* по масштабированию. Оно не хотело поддерживать такие безумные масштабы. А Hg оказались более открытыми.
Бывший фейсбукер, 2024 год
Не хочу сказать, что проект Git должен был повиноваться просьбам Facebook*; я ни в коем случае не думал представить мейнтейнеров в образе «плохих парней». Не стоит делать что-то только потому, что тебя попросил Facebook*. Любопытно, что мейнтейнеры Git, похоже, пару лет спустя сменили свою точку зрения, увидев, что Facebook* вносит полезные улучшения в Mercurial:
Они отправили по почте список проблем с производительностью git. Судя по тому, что я там увидел, отзывов практически не было.
У меня сложилось впечатление, что сообщество разработчиков git почти не имело представления о проблемах с производительностью у крупных репозиториев.
Вопрос в том, заинтересовано ли сообщество git быть конкурентоспособным в случае таких крупномасштабных проектов; тем временем, у Mercurial эта функциональность имеется изначально
Спустя десять лет Git внёс существенные изменения, чтобы улучшить поддержку монорепозиториев.
Сегодня ситуация довольно сильно поменялась, Git уже хорошо работает даже с очень крупными репозиториями (если знать, как это делать правильно).
Бывший фейсбукер, 2024 год
Рассмотренные альтернативы
В 2012 году альтернатив Git было мало. Команда FB* рассматривала возможность использования Perforce с закрытыми исходниками (бывшей системы управления исходниками Google). В одном из первых созвонов с инженерами отдела продаж Perforce команда Facebook* указала на архитектурный изъян в локальной согласованности между узлами чтения и записи. Ответ Perforce не внушил уверенности — инженеры не были в курсе фундаментальной проблемы и у них отсутствовали планы по её устранению.
Рассматривались и другие решения, например, Bitkeeper, но все их быстро забраковали. Последним вариантом остался Mercurial. Его производительность была схожа с Git, но он имел более чистую архитектуру. Git состоял из сложного переплетения кода на Bash и C, а Mercurial проектировался на Python с использованием шаблонов объектно-ориентированного кодинга и с расчётом на расширяемость.
Один из рассматривавших варианты инженеров имел большой опыт работы с Mercurial, поэтому команда решила посетить хакатон по Mercurial в Амстердаме, чтобы изучить вопрос глубже.
А поскольку я раньше много работал с Mercurial, то прежде чем предложить его, я стремился рассмотреть все остальные альтернативы.
Бывший фейсбукер, 2024 год
Они обнаружили систему, которую можно было легко расширять, и сообщество мейнтейнеров, приветствовавших агрессивные изменения, предложенные командой Facebook*.
Думаю, речь конкретно об этом хакатоне, хотя и не уверен. Видео очень в духе начала 2010-х.
Миграция целой организации
После хакатона в Амстердаме команда Facebook* приняла решение. Осталось убедить в необходимости миграции остальную часть компании. Задача была пугающей — инженеры могут очень болезненно воспринимать смену инструментария (вспомним битвы vim и emacs), а смена системы управления исходным кодом — серьёзное дело.
Команда начала подготовку максимально плавно, чтобы не спугнуть других инженеров. То, что последовало за этим, можно считать мастер-классом по миграции внутренних инструментов разработки. Команда несколько месяцев подготавливала коллектив к возможной миграции на Mercurial и составила список аналогов команд и процессов между Git и Mercurial. Она даже изучила частоту исполняемых во всей компании команд Git и специально задокументировала то, как наиболее частые операции будут работать в Mercurial.
Далее она предоставила разработчикам возможность высказать свои опасения и обсудить пограничные случаи, которые могут оказаться сложными в новой системе. Команда предположила, что она погрязнет в спорах о гипотетических проблемах. Но, к своему удивлению, выяснила, что коллеги-инженеры адаптируются и настроены дружелюбно. «Никто не начал жаловаться о какой-то своей особой ситуации».
Лично мне высокоуровневые команды Mercurial всегда нравились больше, чем у git, но не думаю, что причина была в этом. Кстати, мы наняли автора Mercurial.
Бывший фейсбукер, 2024 год
В конце они полностью выступили за миграцию и перевели компанию на Mercurial. Facebook* стала контрибьютором улучшений производительности Mercurial, сделав его лучшим вариантом для крупных монорепозиториев. Эван Пристли расширил Phabricator, добавив поддержку Mercurial. Facebook* использовала концепцию diff Mercurial, чтобы создать паттерн «многослойности», что позволило реализовать новую параллелизацию код-ревью. Бывшие фейсбукеры ушли в новые компании и забрали с собой рабочие процессы, создав маленький, но имеющий вес культ поклонников stacked diff. Позже я познакомился с некоторыми из этих поклонников и решил посвятить себя реализации stacked diff в стиле Mercurial в Git и GitHub.
В заключение
Какой вывод можно сделать из этой истории? Размышляя над цитатами и интервью, я вспомнил старое изречение о том, что многие важные технические решения в истории определялись не технологиями, а людьми.
Как это часто бывает, решение было частично социальным, частично техническим. Я ни капли о нём не жалею.
Бывший фейсбукер, 2024 год
Компания Facebook* выбрала Mercurial не потому, что он был более производителен, чем Git. Она выбрала его, потому что мейнтейнеры и кодовая база были более открыты к сотрудничеству. Инженеры Facebook* лично встретились с мейнтейнерами Mercurial и им понравилась идея партнёрства. Когда нужно было убедить целую организацию, решение приняли благодаря продуманной коммуникации, а не потому, что одна технология была точно лучше другой.
Я думаю, что принятие Mercurial компанией FB* в основном была вызвана гениальными действиями Брайана; их стоит рассматривать как пример при внедрении в компании новых технологий.
Бывший фейсбукер, 2024 год
Meta Platforms*, а также принадлежащие ей социальные сети Facebook** и Instagram*** — признана экстремистской организацией, её деятельность в России запрещена** — запрещены в России
Автор:
PatientZero