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

Если разработчик тратит десять минут на поиск конфигурации, тестов или точки входа, проблема уже не в скорости команды, а в структуре репозитория. Ниже — практический вариант для проекта на Git 2.45 и новее: как разложить код, тесты, документацию и инфраструктуру, чем платить за разные подходы и какие правила закрепить до того, как репозиторий превратится в склад случайных папок.
Сначала определите границы проекта
Репозиторий должен отвечать на четыре вопроса без устных пояснений:
- где находится код, который попадает в продакшен;
- где лежат тесты и как их запустить;
- какие файлы нужны для локального окружения;
- какие действия выполняет CI: сборка, проверка, публикация.
Если на каждый вопрос приходится искать ответ в истории коммитов или спрашивать автора, структура не выполняет свою работу. Названия каталогов могут отличаться, но их смысл должен быть очевиден для нового участника команды.
Структура репозитория — это не каталог всех идей проекта. Это карта ответственности: где менять код, где проверять результат и где запрещено хранить секреты.
Модуль1 в этом материале — часть системы с отдельной ответственностью и понятными границами зависимостей. Это не обязательно отдельный пакет или сервис.
Три рабочих подхода к каталогам
Выбор структуры зависит не от вкуса автора, а от того, как команда меняет и разворачивает систему. Для одного приложения чаще всего встречаются три схемы.
| Подход | Как выглядит | Сильная сторона | Цена |
|---|---|---|---|
| Плоский | src/, tests/, docs/, файлы конфигурации в корне | Быстрый старт и короткие пути | При росте проекта каталог превращается в список несвязанных компонентов |
| Слоистый | controllers/, services/, repositories/, models/ | Привычная схема для CRUD-приложений | Одна функция разносится по нескольким папкам, изменения сложнее проследить |
| По функциональным модулям | billing/, orders/, accounts/ | Код одной возможности находится рядом | Нужны правила зависимостей между модулями |
| Гибридный | Модули внутри src/, общие библиотеки отдельно | Сохраняет границы продукта и переиспользование | Команда должна решить, что действительно является общим кодом |
Для небольшого приложения достаточно плоской схемы. Когда над продуктом работают несколько команд или появляются независимые бизнес-функции, обычно удобнее перейти к модулям. Слоистая структура оправдана там, где архитектура действительно строится вокруг технических слоёв, а не просто повторяет шаблон из другого проекта.
Базовая схема для приложения
Ниже — не обязательный стандарт, а отправная точка для веб-приложения. Дерево схематичное: названия каталогов нужно сопоставить с используемым языком и фреймворком.
project/
├── src/
│ ├── accounts/
│ ├── orders/
│ ├── billing/
│ └── shared/
├── tests/
│ ├── unit/
│ ├── integration/
│ └── fixtures/
├── docs/
├── infra/
│ ├── local/
│ └── production/
├── scripts/
├── .env.example
├── .gitignore
├── README.md
└── CONTRIBUTING.md
Главное здесь не дерево, а правило: функциональный код не смешивается с инфраструктурой, тестовые данные — с рабочими конфигурациями, а инструкции для разработчиков — с документацией продукта.
Как разложить код по смыслу
1. Держите бизнес-функцию рядом
Если изменение заказа требует правок в пяти технических каталогах, ревьюисту трудно понять полный объём работы. Для модульной схемы лучше хранить рядом обработчики, правила, модели и тесты, относящиеся к одной функции. Внутри orders/ допустимы подкаталоги, но они должны обслуживать именно заказы, а не весь проект.
Общий код выносите в shared/ только после повторного использования. Файл, который «когда-нибудь пригодится всем», быстро становится бесхозным контейнером и точкой скрытых зависимостей.
2. Не смешивайте тесты по удобству автора
У тестов должны быть понятные границы:
unit/— быстрые проверки отдельной функции или класса без внешней базы и сети;integration/— проверка связки компонентов, базы данных, очереди или HTTP-сервиса;fixtures/— небольшие подготовленные данные, необходимые тестам;e2e/— пользовательские сценарии, если проект действительно их поддерживает.
Не называйте каталог tests/ «specs», «checks» или «test_code» в разных частях проекта. Одно понятное имя снижает цену поиска и настройки CI.
3. Отделите пример конфигурации от секрета
В репозитории можно хранить .env.example с именами переменных и безопасными значениями-заглушками. Рабочий .env добавьте в .gitignore. Токены, пароли, ключи доступа и приватные сертификаты не должны попадать ни в историю Git, ни в архив релиза. Если секрет уже закоммичен, одного удаления файла недостаточно: значение нужно отозвать и выпустить новое.
Корень репозитория: что оставить на виду
Корень — это первое место, которое видит новый разработчик. Оставьте там только файлы, объясняющие запуск, сборку и правила проекта:
- README.md. Короткий путь от клонирования до первого успешного запуска. Укажите требования к версии среды, команду установки зависимостей и проверочную команду.
- Файл зависимостей. Он должен быть один для выбранного менеджера пакетов или иметь понятное разделение на рабочие и тестовые зависимости.
- Конфигурация CI. Если платформа требует специального каталога, не прячьте рядом копии тех же сценариев без объяснения, какая версия актуальна.
- CONTRIBUTING.md. Правила веток, тестов, форматирования и ревью. Это место для процесса, а не для архитектурной энциклопедии.
- Лицензия и changelog. Добавляйте их, если этого требует распространение проекта или команда ведёт историю изменений вручную.
Не кладите в корень десятки скриптов с именами вроде fix-final-new.py и deploy2.sh. Для повторяемых операций используйте scripts/, а назначение каждой команды опишите в README.
Монорепозиторий или несколько репозиториев
Это отдельное решение от раскладки папок внутри приложения. Монорепозиторий удобен, когда несколько компонентов меняются одним коммитом и должны проходить общие проверки. Несколько репозиториев подходят, когда у компонентов разные владельцы, циклы релизов и права доступа.
Цена монорепозитория — более сложный CI: нужно запускать проверки только для затронутых частей, иначе небольшое изменение будет ждать полный набор сборок. Цена нескольких репозиториев — координация версий и релизов. Если сервисы часто требуют синхронных изменений, граница между ними начинает мешать.
Что ломается в реальных проектах
Общая папка превращается в свалку
Каталоги utils/, helpers/ и common/ начинают принимать всё подряд. Проверяйте каждый новый файл вопросом: кто его владелец и какая зависимость делает его общим. Если ответа нет, файл должен остаться внутри конкретного модуля.
Тесты не соответствуют коду
Перенесли функцию, но оставили тест в старом каталоге — через несколько месяцев структура начинает врать. При перемещении модуля перемещайте его тесты в том же изменении и проверяйте, что CI действительно их запускает.
Инфраструктура копируется без контроля
Файлы для локального Docker-окружения, staging и production часто расходятся. Разделите их по средам в infra/, явно назовите различия и не храните в репозитории реальные значения секретов. Если два конфига почти одинаковы, автоматизируйте сборку из общего шаблона только после того, как различия стали стабильными: ранняя шаблонизация усложняет отладку.
Документация устаревает первой
Добавляйте в README проверяемую команду и ожидаемый результат. Если инструкция не запускается на чистом окружении, это не документация, а воспоминание автора о том, как проект когда-то работал.
Когда какой подход выбирать
- Небольшое приложение с одной командой. Начните с
src/,tests/,docs/иinfra/. Не создавайте десять уровней вложенности заранее. - Продукт с несколькими бизнес-функциями. Разложите код по модулям внутри
src/и определите допустимые зависимости между ними. - Несколько приложений и общие пакеты. Рассмотрите монорепозиторий, если изменения часто проходят через несколько компонентов. Иначе разделение репозиториев может быть дешевле в поддержке.
- Проект с разными командами и правами доступа. Сначала определите владельцев и границы публикации, затем выбирайте каталоги. Структура без ответственных быстро теряет смысл.
Что сделать дальше
Откройте текущий репозиторий и выпишите пять сценариев: новый разработчик запускает проект, автор добавляет модуль, CI выполняет тесты, команда меняет инфраструктуру, релиз публикуется. Для каждого сценария зафиксируйте путь, команду и владельца. Затем удалите дублирующие инструкции, перенесите секреты за пределы Git и добавьте проверку, которая запускается на чистом клоне.
После этого измеряйте не количество папок, а время до первого успешного запуска, долю изменений, затрагивающих несколько модулей, и число падений CI из-за неверных путей или отсутствующих файлов. Эти показатели покажут, помогает ли выбранная структура, а не просто выглядит ли она аккуратно.
Создатель презентаций: Структура и текст каждого слайда: заголовки-утверждения, одна мысль на слайд, заметки докладчику.
Спросить за 150 ₽Источники: Git documentation: Repository Layout, Git documentation: gitignore
Частые вопросы
Нужно ли сразу строить структуру по бизнес-модулям?
Где хранить тесты: рядом с кодом или в отдельном каталоге?
Можно ли хранить .env в Git, если репозиторий приватный?
Когда монорепозиторий становится проблемой?
Что делать, если команда уже привыкла к хаотичной структуре?
Нужно ли выносить каждый повторяющийся файл в shared или common?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.