Как стать автором
Обновить

Комментарии 67

> Каков масштаб нашей проблемы? Вот некоторые цифры: 6 млн коммитов, почти 2 млн отдельных файлов. Общий размер со всей историей репозитория — 2 ТБ.

В статье Microsoft утверждается, что исходный код Windows — «всего» 300 Гб, что почти в 7 раз меньше.

К тому же, здесь есть ещё другая проблема — если хочется работать со всем репозиторием целиком (т.е. не делать narrow clone и shallow clone), то git предполагает, что все объекты будут присутствовать локально, что ограничивает размер репозитория размером локального диска на машине. Если не рассматривать HDD, то типичный объем локального диска в современных ноутбуках составляет от силы 500 Гб, и репозиторий Яндекса туда просто не поместится. Даже если взять SSD на 2 Тб (вроде Apple сейчас даёт такую опцию для каких-то компьютеров), то ни для чего больше в системе места не останется.

Я не утверждаю, что решение от Яндекса лучше чем решение от Microsoft: наоборот, мне очень нравится идея с git vfs. Просто оно не решает поставленную задачу самым эффективным способом с учётом стоимости SSD ёмкостью в несколько терабайт, которые иначе нужно было поставить каждому разработчику компании.

Ну как бы VFS это вроде бы Virtual File System и решает она те же проблемы и вроде бы точно так же как и Яндексовый Arc. Т.е. ничего она целиком не высасывает.

Да, Вы правы, я как-то не обратил на этот момент внимание, когда читал про git vfs. В любом случае, для репозитория Windows (в 7 раз меньше Яндекса) приводятся цифры по скорости работы git status, git checkout и прочего, и уже на этом объеме эти операции занимают по несколько секунд.

git status, git checkout и прочего, и уже на этом объеме эти операции занимают по несколько секунд

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

Скорее всего 300гб исходников без истории, когда в Я 2тб — включая историю

Мой опыт работы в геймдеве говорит мне, что размеры репозитория, указанные в статье микрософта, позволяют просто использовать Git на SSD с комфортной производительностью.

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

просто использовать Git на SSD с комфортной производительностью.

А связь с сервером?
Все эти merge, push и т.п.
VFS for Git — действительно очень интересный проект с похожими на наши целями и средствами. В Microsoft пошли несколько иным путем и добавляют виртуализацию ФС и ленивую загрузку объектов прямо в git за счет фигурного вырезания фильтров для sparse checkout и ignore файлов. Мы пробовали применить похожий подход в mercurial и довольно быстро поняли, что либо придется переписать почти всю vcs, либо мириться с кучей пограничных случаев, когда безобидная операция (тот же git log) начинает выкачивать все содержимое репозитория локально.
Когда наш проект начинался еще одним недостатком GVFS было отсутствие поддержки linux, что для нас было критичным. Но с тех пор экспериментальная поддержка появилась.
А смотрели в сторону патчей для hg от Facebook? Насколько я понимаю, они тоже делали что-то похожее на то, что вам нужно.

Да, смотрели. И да, это действительно очень похоже на то, что мы делаем. Но там до сих пор есть прекрасное https://github.com/facebookexperimental/eden/issues/7#issuecomment-473357543
Есть байка, что они выложили это в open source случайно и поэтому эти патчи невозможно собрать и использовать за пределами фейсбука.

Вместо того, что бы разбить все это на мелкие репы и сделать инструмент высшего уровня для управления ими программисты продолжают умножать энтропию рожая N+1 систему контроля версий.
Я полагаю, что Яндекс рассматривали эту возможность, и даже есть примеры больших репозиториев, которые так делают — это Chromium и Android, но согласно, например, этой статье, у этой модели тоже есть серьезные недостатки, например очень низкая производительность и необходимость скачивать эти репозитории локально, что весьма сложно делать, если репозиторий занимает несколько терабайт.

Получается, что при любом выбранном сценарии — все равно пилить какой-то свой тулинг.

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

Вообще как я для себя понимаю основную мотивацию делать такое — это размен инженерного времени на написание навороченных тулзов для всего этого хозяйства вместо постоянной однотипной работы по обновлению библиотек в сотне различных репозиториев. Когда каждое такое обновление занимать может по несколько месяцев. Это автоматизируется частично, но всеравно будет куча автоматических коммитов с изменением версии пакета. Я работал в компании с очень небольшой кодовой базой, около 4-6М строк кода на питоне, разбросанного по примерно 300-400 репозиториям. И обновление какой-нить базовой библиотеки, очень непростоя и главное неинтересное занятие. А в Яндексе я подозреваю должно быть раз в 10 больше кода как минимум.
В монорепозитории же это будет 1 атомарто откатываемый коммит. Но нужно писать и поддерживать все эти тулзы. Что я думаю будет меньшей платой и с большим бенефитом потенциально.
И обновление какой-нить базовой библиотеки, очень непростая и главное неинтересное занятие.

Которая решается пакетным менеджером и инженерными гайдлайнами (semantic versioning, использование "плавающих" версий зависимостей, либо даже просто ссылками на git ref).

Которая решается пакетным менеджером

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

и для серьезного проекта я бы хранил всё в репе с основным кодом.

а еще версии и даже целые библиотеки умеют исчезать в никуда из реп внешних пакетных менеджеров.
Зачем внешних? Локально (в смысле в сети организации) поднять что гит-, что, например, Maven-репозиторий — не проблема. Артифактори там всякие, нексусы есть.

Для этих целей у нас есть миррор для внешних репозиториев.

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

Оно обновится автоматом при деплое/билде, а затем прогонятся тесты.


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


Разве что для мультирепо PR-ов придется больше создать.


Хотя делать мега-PR для всей монорепы та еще затея — по моему опыту такие мега-PR часто ломают продакшен, ибо покрытие тестов никогда не бывает 100%, а люди особо не вглядываются (либо проблема может быть не очевидна).


Бай зе вей — https://dependabot.com/

Фиксирование версий библиотек вроде давно придумали. В монорепозитории оно должно работать точно так же.

Тут правда другая опасность есть. Застрять на версии 200х года и когда таки придется обновиться словить все проблемы совместимости за 15 лет разом. Но при должном отслеживании и регулярном обновлении все должно работать без проблем.
Вместо того, что бы разбить все это на мелкие репы и сделать инструмент высшего уровня для управления ими программисты продолжают умножать энтропию рожая N+1 систему контроля версий.


Есть доводы и за и против монореп.

Исходя из того, что монорепы выбрали не самые глупые разработчики, которых могут себе позволить богатейшие Google, Microsoft и пр. — смысл в монорепах есть.

В предлагаемом вами варианте — будут другие проблемы, например, с совмещением версий для кусков отдельного продукта.

Что способно ухудшить итоговое качество кода, увеличить затраты на интеграцию.

VCS — это сервисное для разработчика ПО, обслуживающее потребности разработчиков.

Подстраиваться под менее удобный стиль работы из-за ограничений ПО?
Зачем? Если можно взять другое ПО или создать своё.

Пример из жизни:
git. Был создан Торвальдсом для удобства разработки Linux.

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

Исходя из того, что монорепы выбрали не самые глупые разработчики, которых могут себе позволить богатейшие Google, Microsoft и пр. — смысл в монорепах есть.

Это звучит как карго-культ. Из серии — они успешны, потому что используют монорепо. Давайте так же. Это очевидно, что тупиковый вариант. Наоборот — нужно изучать опыт крупных и неглупых разработчиков и делать по-своему, учитывая ИХ ошибки (любые люди ошибаются) и учитывая СВОИ реалии.


В предлагаемом вами варианте — будут другие проблемы, например, с совмещением версий для кусков отдельного продукта.

в транк-бейзед, в целом, свой ворох проблем. Который накладывается на СВОЮ разработку. Я почти наверняка уверен, что яндекс может себе позволить разработку своей библиотеки каких-нибудь стандартных контейнеров для бОльшей части своих продуктов, а не тащить внешние зависимости. Но вот со штуками вроде фронтов на html+js такое уже не прокатит.


VCS — это сервисное для разработчика ПО, обслуживающее потребности разработчиков.

+1


git. Был создан Торвальдсом для удобства разработки Linux.

но опять же это не означает, что надо всех загонять в git. Есть люди, работающие в hg, и вполне счастливые. Другой вопрос, что именно git стал стандартом де-факто и модель форков github'а тоже стала стандартной моделью разработки (мне форки, кстати, зачастую не нравятся)

Исходя из того, что монорепы выбрали не самые глупые разработчики, которых могут себе позволить богатейшие Google, Microsoft и пр. — смысл в монорепах есть.

Это звучит как карго-культ.


Карго-культ для Яндекса-то?
git. Был создан Торвальдсом для удобства разработки Linux.

но опять же это не означает, что надо всех загонять в git.

Мой посыл был о другом:

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

Можно и наоборот — сделать инструмент под себя. Конечно, если у вас есть такая техническая и финансовая возможность.
Предложение для обсуждения. Всю дорогу я повторял слова «как в Git». И в целом наш план остается прежним: интерфейсом повторять Git. Но чем больше мы это делаем, тем больше понимаем, что это не очень работает.


Вот с этого момента хотелось бы поподробнее :). Почему не работает? Какие команды вы планируете поддерживать, а какие нет? Мне кажется, если ограничиться некоторым подмножеством высокоуровневых команд и не предоставлять низкоуровневый интерфейс, то должно быть достаточно похоже для большинства, без необходимости полностью имитировать объектную модель Git (которая довольно плохо масштабируется для совсем больших репозиториев).

Также, возможно я что-то пропустил, но хотелось бы узнать, как вы реализовали аналог «git log » и «git log »? Как отслеживаете переименования? В «оригинальном» git log это затратные операции, потому что git не хранит информацию о переименованиях отдельно, и соответственно git log при всём желании не может показать историю для конкретного файла без того, чтобы сканировать все коммиты в репозитории.

В целом вы правы, мы планируем поддерживать высокоуровневые команды git по степени востребованности нашими пользователями. Но, например, пользователи переходящие с svn сильно удивляются количеству действий, которые надо сделать для отправки небольшого изменения на ревью: arc checkout -b + arc add + arc commit + arc push + arc pr create — это 5 действий вместо одного привычного им svn commit. Поэтому мы движемся в сторону создания интерфейса более высокого уровня, который упрощал бы типичные сценарии. Это в чем-то похоже на подход git-flow с поправкой на то, что у нас trunk based модель.


Что касается arc log, то тут действительно мы сильно отошли от гита. Информацию о копированиях мы храним прямо в графе объектов, поэтому нет необходимости какими-то эвристиками извлекать её из данных. Операция вычисления лога для пути — серверная, поэтому нет проблем с доступом ко всему графу коммитов. В аккуратном представлении он легко влезает в память и его обходы получаются очень быстрыми. Для определения влияющих на путь коммитов мы отдельно поддерживаем индекс файлов, затронутых каждым коммитом. Он тоже оказывается не безумно большим. В результате на клиенте достаточно загрузить только коммиты попавшие в лог.

Arc?! Это случайно не тот самый Arcanist, a command-line interface to Phabricator?

Судя по всему, не тот же самый. В Facebook не git, а mercurial (и это здорово, потому что последний и быстрее на порядок, и удобнее на таких объемах и при безветочной схеме с trunk-based development, которая, похоже, становится популярным стандартом де-факто).


Думаю, что arc, что arcadia обыгрывают имя сооснователя Яндекса.

НЛО прилетело и опубликовало эту надпись здесь

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


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


А вот по части невозможности глобальных рефакторингов, автор имхо просто ошибается. В нашем репозитории я вполне проделывал вещи вроде grep | xargs | sed, разве что вместо простого grep там был вызов серверного code search, а все остальное естественным образом быстро работало в нашей vcs и загружало только затронутые файлы. Невозможность сделать ревью таких изменений до возникновения конфликтов мне тоже кажется надуманной.

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

Я думаю, что принципиальным вопросом является то, как сделан процесс разработки — разрабатываем ли мы коробочный продукт для наших заказчиков (и тогда мы связаны необходимостью поддержки нескольких версий) или пилим какой-нибудь SaaS (который может существовать в единственной версии — текущей, т.е. крайней, но с поддержкой, например, нескольких версий API). Это два разных подхода и мне было бы очень интересно услышать, как, например, в рамках trunk-based легко и безболезненно держать разработку нескольких версий одного коробочного продукта (ну, например, кликхаус вполне подойдет, наверное?).

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

Я постоянно вынужден создавать ветки в нескольких репозиториях и отправлять их на ревью. Да, всё заливается вместе, CI, вот это всё, но это менее удобно, чем создать ветку в одном репозитории. Навигация по ФС усложняется, т.к. есть лишняя вложенность. Бывает, что команды не выносят общий код в общее место, а коммитят в «свой» репозиторий, чтобы «упростить» ревью, из-за чего другие даже не знают про то, что уже что-то написано, и создают велосипеды.

И это при том, что я лично выкачиваю все репозитории из зонтика — места хватает, ничего не тормозит.

Да, монорепа требует дополнительных усилий. Но эти усилия даже близко не сопоставимы с усилиями Гугла (или даже Яндекса), т.к. и кода меньше. А когда кода столько же, то и средства по идее должны быть.
Я постоянно вынужден создавать ветки в нескольких репозиториях и отправлять их на ревью. Да, всё заливается вместе, CI, вот это всё, но это менее удобно, чем создать ветку в одном репозитории.


Вы путаете теплое с мягким. Ветки вас заставляет создавать git flow, а не сабмодули. Не используйте git flow — не будет и миллиарда веток в сабмодулях.
Вообще, «монорепе» обычно противопоставляется «микрорепы», когда границы проводятся по каждой библиотеке. Истина же где-то по-середине — слишком мелкое деление так же вредно как и отсутствие его. Qt5 разделена на примерно 50 сабмодулей, кажется, это слегка перебор (и, естественно, идут разговоры о «монорепе», как будто по середине ничего нет)

А как тогда работать вне концепции веток? Мастер ветка и переключение функционала через feature gate ?

Мне очень нравится gerrit. Проблема в том что он проприетарный (в том смысле что нет опен сорс аналога уровня GitHub), страшный как смерть (сейчас уже получше, но всё равно...), поэтому о нём мало кто знает и почти никто не пользуется. Мой поинт в том, что гитхабовская схема с pull request, которая _форсит_ создание feature branches — не единственная возможная. Просто там ветки — это деталь реализации, зачем-то торчащая наружу.
В общем и целом Gerrit по процессу очень похож на внутренний яндексовый велосипед для ревью и прекоммит проверок — по факту вы и там и там коммитите «напрямую в транк» безо всяких pull requests и фича веток.
Что, конечно же, не отменяет возможности создать feature branch по желанию. Просто Gerrit не навязывает схему с pull requests и\или git flow.

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


В общем. Положим, разраб взял какую-то фичу. Начал реализовывать. Как в концепции единой ветки его код попадает в "мастер"? Получается, должен быть пайплайн по тестированию. А если кто-то успел за 5 минут до вливания изменений влить несовместимые изменения? Не будет ли это кошмаром хуже, чем текущий бардак с фичеветками в гитхабе/гитлабе?


Заодно — phabricator смотрели?

В общем. Положим, разраб взял какую-то фичу...


В зависимости от размера проекта, есть два подхода. В случае небольшого проекта, если изменения не конфликтуют по коду (это Gerrit сам ловит) и мы условно не боимся, что изменения конфликтующие, их можно протестировать независимо и потом влить в мастер. Если изменения таки конфликтуют, можно указать разработчику на зависимость и попросить отребейзить изменение на свежий мастер. В общем, ничего нового.
Второй подход заключается в том, чтобы делать staging branch — когда пачка изменений разных разработчиков как-то черри-пикается друг на друга и проверяется в таком виде перед мержем в мастер. Минус что если один коммит ломает что-то, то остальные надо stag'ить заново. Плюс — мы всегда собираем то, что будет в итоге в мастере. Также, этот подход необходим, когда не хватает железа тестировать каждый коммит отдельно. Пример — всё та же Qt, матрица тестируемых систем достаточно большая и нет возможности прогонять тесты ~6 часов для каждого коммита в отдельности.
К сожалению, я не в курсе, сколько второй способ требует усилий, чтобы его реализовать (никогда администрировать gerrit не приходилось).

Заодно — phabricator смотрели?

Нет, но коллега на текущей работе пользуется и очень хвалит. Сами мы вообще на svn пока что=(
Изменения, состоящие из нескольких локальных коммитов, в gerrit попадают через git push. Это по сути создание ветки, пусть и без явного указания имени.

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

Ну и вообще, Gerrit умеет работать с зонтичными репозиториями из коробки? Есть какой-то способ группировки в одно ревью? Атомарная заливка в несколько репозиториев? Автоматическое обновление зонтичного репозитория после обновления вложенных? Или нужно писать свои тулы, более сложные, чем для монорепозитория?

Да и обновление в gerrit'е происходит с использованием change id, что куда менее удобно, чем с force-with-lease обновить feature-ветку с конкретным именем.

Что касается миллиарда feature-веток, то изменения перед проверкой и вливанием можно автоматически переставлять на конец нужной ветки, а саму ветку удалять после вливания. Ничего лишнего — ветки только для версий, а также для фич в разработке или на ревью.

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

Если же не нравятся отдельные merge-коммиты в истории, то у них есть плюс — все изменения по одной задаче сгруппированы вместе. Имеет смысл настроить в CI non-fast-forward merge как минимум для изменений из более чем одного коммита, а с учётом специфики git'а, в котором не сохраняется метаинформация о ветках и тегах (автор и, особенно, время изменения), лучше даже поступать так и для изменений из одного коммита.
У меня возникает стойкое ощущение, что у вас слишком гранулярное деление на сабмодули. Естественно, никакой геррит вам тут не поможет (и никакой тулинг не поможет, если конечно вы не гугл и у вас есть десятки человеколет на написание этого тулинга). Только это не проблема сабмодулей, это проблема того, как вы их готовите.
Если вы думаете, что в Яндексе постоянно вот так вот приходят и делают коммиты затрагивающие всё дерево сорцов, то вы ошибаетесь — даже «банальное» переименование Stroka в TString делалось поэтапно (если мне не изменяет память).
А между сервисами совместимость _обязана_ быть между версиями. Я конечно мог бы прийти в соседнюю команду и на их java написать использование нового поля, закоммитить всё это одним коммитом… Но какой в этом толк, если 2 сервиса всё равно должны работать в любой комбинации (старый-старый, старый-новый, новый-новый...) на случай факапа и возможного отката одного из них? А еще релизный цикл разный — один сервис катается быстрее чем второй…
Собственно «правильное» деление на сабмодули должно быть по слабо зависящим друг от друга частям — например, репозиторий с сорцами 3rdparty вполне такой кандидат. Или ассеты, если вы разрабатываете игру.
Если у вас одна фича постоянно требует связанных коммитов — подумайте о слиянии зависимых сабмодулей в один. Или подумайте о том, почему эти репозитории так зависимы — может, надо использовать другой формат общения между ними?
А между сервисами совместимость обязана быть между версиями. Я конечно мог бы прийти в соседнюю команду и на их java написать использование нового поля, закоммитить всё это одним коммитом… Но какой в этом толк, если 2 сервиса всё равно должны работать в любой комбинации (старый-старый, старый-новый, новый-новый...) на случай факапа и возможного отката одного из них? А еще релизный цикл разный — один сервис катается быстрее чем второй…

Как это у вас реализовано? В случае транк-разработки я вижу вариант только при инстанцировании новой версии сервиса попросту копировать все дерево файлов из старого каталога service.v1 в новый каталог service.v2
Но тут, прошу прощения, я слаб. Ибо в гите все как раз просто — заводишь два отдельных бранча и понеслась.

Сервисы общаются между собой при помощи неких форматов. Это может быть жисон, когда один сервис запрашивает по http данные у другого. Это может быть protocol buffers, когда один сервис подкладывает файлики другому. Это может быть YT… Вариантов куча. Большинство форматов умеют в опциональные поля — жисон, протобуф. Собственно, при добавления нового поля потребитель проверяет — а новое поле есть? — тогда используем его, иначе работаем «по-старинке».
Сильную попаболь доставлял MMS — там да, чтобы сделать новую версию, приходилось натурально копипастить исходники. Но это, скорее, исключение (к счастью, было нужно редко) и, возможно, flatbuffers тут подошли бы лучше.
Без такой совместимости не получится сделать надежную систему — у вас факап на проде, а откатываться нельзя или очень сложно.

PS: Но я уже больше года не работаю в Яндексе, так что мои знания могут быть немного устаревшими=)

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

Да, новую реализацию стараются прикапывать рядом, не ломая старую. Но оно обычно не противопоставляется старому функционалу, а расширяет его.
Мы работаем не по git flow :)
Но, как и комментатор выше, я не могу представить себе модель разработки без использования веток (при условии, что есть предварительное ревью кода).
Я не призываю полностью отказаться от веток, я ярый противник «технических» веток, когда feature branch создается на любой чих просто потому что «так все делают» или потому что так хочет тулинг (github).
Надо поддерживать N предыдущих версий — вперед, релизные ветки рулят.
Начали работать над новой версией библиотек — вперед, долгоиграющая feature branch.
Портируете проект с автотулз на cmake? Тут тоже пригодится feature branch.
Вот только не надо создавать ветку чтобы убрать\добавить пробел в выражении=)
Я правильно понимаю, что вы так и не импортировали репозиторий в Git? И поэтому не знаете, может он достаточно хорошо работает на ваших объёмах и вам не нужно изобретать велосипед?

А вот цитата:
За время подготовки доклада git-svn, к сожалению, не смог сконвертировать весь наш репозиторий целиком.

То есть вы сначала сделали свою VCS, потом начали писать про неё доклад и только потом попытались протестировать работу Git'а?

Мы тестировали работу гита на отдельных фрагментах репозитория и результаты нас не радовали. Для доклада мне хотелось получить какие-то числа для всего репозитория, чтобы было проще сравнить разные vcs.
У нас нет оснований предполагать, что от конвертации всего репозитория git магическим образом начнет работать лучше. Там будут те же принципиальные проблемы, что и с mercurial — многие операции требуют обхода всего дерева каталогов и их трудоемкость растет с размером репозитория. Те цифры производительности, которые мне удалось на скорую руку получить, эти предположения подтверждают.

Если сделать svn co Аркадии, потом сделать git init && git add && git commit (то есть, импортировать всё без истории коммитов), а потом попробовать с этим поработать, то, например, git status будет занимать 3 секунды. Не очень удобно.

Ну кстати git status, который отрабатывает за 3 секунды — это не так уж плохо для git-репозитория такого размера :). Вот с вещами вроде git log и git blame у вас правда будет всё очень грустно :).

Ребята, вы всё делаете не правильно. И сейчас я объясню почему.



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


мы не пытаемся загрузить все заранее. И всякие тяжелые операции мы выносим на сервер

Замечательно. Почти любые операции прибивают разработчика к серверу и зависят от скорости интернета. Современные разработчики вспоминают эту особенность SVN как страшный сон, а вы так и застряли в прошлом веке, не сумев в децентрализацию. Работа в поезде, самолёте, в окружении 30 файфай-точек, в подвальном кафе, через забитый открытый файфай? Не, только в офисе и по проводу.



И какой смысла повторять чей-то апи не полностью? И при этом брать за объект для подражания набор команд, который не ругал за бестолковость только ленивый. Почему было не взять за основу тот же Меркуриал, который более дружелюбен к человекам? Более того, дальше вы пишете:


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

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


Довольно важная операция для системы контроля версий — это поиск наименьшего общего предка для двух коммитов.

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



А за баловство с ребейзами в приличном обществе вообще руки отрывают. Они приводят к куче сломанных коммитов в истории. Либо к куче лишней работы по исправлению всех ребейзнутых коммитов. Особенно это весело при использовании bisect. Ах да, у вас же и bisect-а, по всей видимости, нет.

Этот комментарий сделал мой день. Спасибо.


По поводу ребейз вопрос. Я его не люблю. По двум причинам. Первая — это отличный способ зафакапить всю историю, но тут совет один — не делайте ребейз на ветках, отличных от своей личной. Т.е. ребейз на мастере или dev ветке — запрещаем. Вторая ипостась ребейза — это выравнивание своей истории коммитов при мерже в мастер и схлопывание истории разработки фичи в один meaningful коммит. Не вижу здесь проблем, кроме того, что ребейз слишком мощен и может отстрелить обе ноги, но это явно лучше, чем 100500 веток на графе коммитов и лишние MR-commit'ы

НЛО прилетело и опубликовало эту надпись здесь

Не могу ответить однозначно. Это из разряда того, что один и тот же результат в гите можно получить слишком разными способами и разными командами. Хочется чего-то вроде Python Zen...

А что плохого в том, чтобы проверяемые изменения ребейзить? История куда легче просматривается, чем в случае обычного merge. Bisect работает, коммиты не ломаются.

Вот релизные ветки и trunk/master переделывать действительно не стоит, ну так у многих систем есть защита от force-изменения веток, подпадающих под указанный regexp.

P.S. Насколько я знаю, с чем у текущей монорепы Яндекса проблемы, так это с тем, что rebase -i нет, а для причёсывания перед вливанием бывает полезно.
Вот релизные ветки и trunk/master переделывать действительно не стоит, ну так у многих систем есть защита от force-изменения веток, подпадающих под указанный regexp.

Все так. Так и должно быть.


А что плохого в том, чтобы проверяемые изменения ребейзить?

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

По первой ссылке:
Автор почему-то считает, что в rebase коммиты добавятся в конец веток. В реальности же есть CI, который не даёт вливать ветку с ошибками. В этом случае коммит g можно не ставить в конец, а объединить с тем, где добавили ошибку, и только после этого повторно отправить на вливание. Лично я чаще всего именно так и делаю.
Проблема с bisect'ом преувеличена. Не знаю как где, но у нас применяется редко, т.к. постоянные пересборки и проверки занимают достаточно много времени, обычно быстрее найти ошибку в дебаге.
Также там говорится, что исправление конфликтов во время мержа проще. Но почему? Будут всё те же конфликты, вот только не разбитые по изменениям, как при rebase, а одной кучей. И править придётся сразу кучу, а не по частям. Да и читать историю, когда исправления конфликтов не внесены в оригинальные коммиты, а вынесены в отдельный merge-коммите, куда сложнее.

Вторая и третья ссылки вообще несерьёзные, ни одного реального примера. Ну и опять же, CI такое должен ловить при прогоне тестов.

Я пользуюсь rebase (часто интерактивный) с момента перехода на git в 2012 году, проблемы возникают очень редко и всегда быстро отлавливаются. Зато вот с merge-коммитами проблем хватает. Например, если blame указывает в merge-коммит, то сразу не понимаешь причину изменения логики, приходиться реально открывать историю и просматривать коммиты в ветке. Инструменты часто не умеют отматывать blame назад по нелинейной истории. Часто в merge-коммите не указана задача, т.к. подливается, например, ветка версии. Или разработчик может внезапно закоммитить merge-коммит как обычный, т.к. «что-то поменялось, а снова мержить не хотелось», убив тем самым всю ветку целиком, схлопнув все изменения и потеряв всю метаинформацию — реальная история, к сожалению.

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


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


Ну и про CI — вы реально предлагаете гонять CI по всем коммитам, а не только по последнему? И это в ваших условиях, когда "пересборки и проверки занимают достаточно много времени". Впрочем, вам бы стоило прежде всего решить проблему долгой сборки, так как она много чему мешает. Не только использованию bisect.

kikht Про поддержку высокоуровневых комманд Git и интеграцию с существующим тулингом: может попробовать прикидываться прямо git бинарником для других тулов типа редакторов/ide, чтобы не писать кастомные интеграции для них?

Это бы работало, если бы интеграции работали только через вызов бинарника git. На самом деле они часто ходят напрямую в файлы внутри .git Либо через libgit2, либо вообще полностью самостоятельно.

Справедливо

Актуальненько ;) спасибо за разъяснения.

Зарегистрируйтесь на Хабре , чтобы оставить комментарий