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

В репозитории, где исходники, Docker-файлы, миграции, тесты и секреты лежат вперемешку, новая задача начинается с археологии. Разработчик тратит время на поиск точки входа, ревьюер не понимает, что попадёт в релиз, а CI запускает не тот сценарий. Ниже — практическая схема для командного Git-репозитория веб-сервиса: что держать в корне, что убирать в каталоги и как выбрать структуру для монорепозитория. Ориентир — Git 2.44 и новее; сами каталоги проекта не зависят от версии Git.
Сначала разделите Git и проект
Git-репозиторий состоит из рабочей директории и служебного каталога .git. Рабочая директория содержит файлы проекта, которые видит команда: исходный код, тесты, документацию и конфигурацию сборки. В .git Git хранит историю коммитов, ссылки на ветки, индекс и локальные настройки.
Каталог .git не нужно включать в архив приложения, копировать на сервер или редактировать вручную. Удаление этого каталога уберёт локальную историю и связь рабочей директории с репозиторием, но не удалит сами файлы проекта.
Хорошая структура отвечает на три вопроса без чтения всей документации: где изменить поведение приложения, где проверить изменение и что попадёт в поставку.
Сноска к термину «рабочее дерево». Рабочее дерево — это текущее состояние файлов на диске, с которым вы работаете. Git сравнивает его с индексом и последним коммитом, чтобы показать изменённые, добавленные и удалённые файлы.
Что обычно лежит в корне
Корень репозитория — не склад для всех файлов. Здесь должны оставаться документы и настройки, которые объясняют проект целиком или запускают стандартные процессы команды.
README.md— назначение проекта, быстрый запуск, обязательные зависимости и ссылка на подробную документацию.LICENSE— лицензия, если проект распространяется с такими условиями..gitignore— локальные артефакты, кэш, виртуальные окружения, сборка и файлы с секретами..editorconfig— базовые правила отступов, перевода строк и кодировки, если команда их фиксирует.- Файл зависимостей и lock-файл — например, для языка или пакетного менеджера проекта. Lock-файл фиксирует конкретное разрешение зависимостей и обычно должен попадать в репозиторий приложения.
- Конфигурация CI — в том месте, которое требует выбранная платформа: например, каталог
.github/workflowsдля GitHub Actions. - Конфигурация контейнеров, линтеров и сборки — только если она относится ко всему проекту.
Имя файла с переменными окружения не означает, что секреты можно коммитить. В репозитории храните шаблон вроде .env.example без токенов и паролей, а реальные значения передавайте через секрет-хранилище CI, настройки оркестратора или переменные окружения.
Рабочая схема для одного приложения
Для веб-сервиса с одним продуктом удобно начинать с такой логики:
src/илиapp/— исходный код приложения. Выберите одно имя и закрепите его в README.tests/— автоматические тесты. Если проект делит их на уровни, используйте подкаталоги вродеunit,integrationиe2e.docs/— архитектурные решения, инструкции для сопровождения и описание нестандартных процессов.scripts/— повторяемые служебные операции: локальная инициализация, проверка данных, подготовка релиза.config/— конфигурация приложения, не содержащая секретов. Если настройки живут рядом с кодом и так принято в конкретном фреймворке, отдельный каталог не обязателен.db/илиmigrations/— миграции схемы и связанные с ними файлы. Не смешивайте их с временными дампами базы.public/,static/илиassets/— статические ресурсы, если их обрабатывает именно этот проект.deploy/,infra/илиops/— инфраструктурные манифесты, настройки прокси и сценарии поставки.
Это не обязательный стандарт Git. Git безразлично, назовёте ли вы каталог src или app. Важнее, чтобы один тип содержимого имел одно очевидное место, а исключения были объяснены.
Что не стоит складывать в репозиторий
- секреты, приватные ключи и реальные файлы окружения;
- папки зависимостей, которые пакетный менеджер умеет восстановить;
- собранные файлы, если они создаются CI и публикуются в артефакты;
- логи, временные выгрузки и дампы с пользовательскими данными;
- локальные настройки IDE, если команда специально не договорилась хранить их централизованно.
Исключение из Git не равно защите уже опубликованного секрета. Если ключ попал в историю, его нужно отозвать и выпустить новый, а очистку истории проводить отдельно и согласованно с командой.
Три варианта организации кода
Структура зависит от границ поставки. Небольшое приложение, набор независимых сервисов и монорепозиторий не должны выглядеть одинаково.
| Подход | Как выглядит | Плюс | Цена |
|---|---|---|---|
| Один сервис | Корень содержит src, tests, docs и настройки поставки | Просто искать код и запускать CI | При росте проекта корень быстро перегружается |
| Монорепозиторий | apps/ для приложений, packages/ или libs/ для общих компонентов, общая CI-конфигурация в корне | Единая история изменений и общий код | Нужны правила зависимостей, области сборки и владельцы каталогов |
| Несколько репозиториев | Каждый сервис имеет собственный корень, тесты и pipeline | Независимые релизы и права доступа | Сложнее синхронизировать совместные изменения и версии контрактов |
Монорепозиторий не означает, что всё можно положить в один каталог. У каждого приложения должны быть собственные исходники, тесты и конфигурация, а общий код — отдельная библиотека с понятным владельцем. Если импортировать файлы соседнего приложения напрямую, границы быстро исчезнут.
Правила, которые стоит зафиксировать
Каталоги сами по себе не предотвращают хаос. Команда должна договориться о правилах и сделать их видимыми в README или CONTRIBUTING.md.
- Опишите точку входа. Укажите, какая команда запускает приложение, тесты, линтер и сборку. Проверка: новый участник может выполнить базовый сценарий без чтения исходников.
- Закрепите владельцев зон. Для монорепозитория назначьте ответственных за
apps, общие библиотеки и инфраструктуру. Проверка: по пути файла понятно, кого позвать на ревью. - Отделите исходники от результатов сборки. Сборочные каталоги не должны одновременно быть местом ручного редактирования. Проверка: удаление результата сборки не ломает исходный проект.
- Сделайте конфигурацию воспроизводимой. Шаблоны и безопасные значения храните в репозитории, секреты — вне его. Проверка: приложение поднимается на чистом окружении после заполнения описанных переменных.
- Проверяйте структуру в CI. Запретите случайные дампы, секретные расширения и файлы слишком большого размера. Проверка: ошибочный файл получает понятное сообщение до слияния ветки.
Что ломается первым
Один каталог для всего
Файлы маршрутов, обработчики, тесты и миграции в одном каталоге сначала экономят несколько переходов, но усложняют навигацию уже при первых десятках модулей. Разделяйте код по ответственности, а не по тому, кто последним менял файл.
Папка utils превращается в свалку
Функция, которую нельзя отнести к предметной области, часто попадает в utils. Через несколько месяцев там оказываются форматтеры, клиенты внешних API и бизнес-правила. Если у функции есть конкретный контекст, положите её рядом с этим контекстом или выделите отдельный модуль.
Общий код связан с приложениями напрямую
В монорепозитории библиотека не должна незаметно импортировать внутренние файлы приложения. Иначе изменение одного сервиса потребует непредсказуемой пересборки соседей. Зафиксируйте публичные точки импорта и проверяйте зависимости в CI.
Документация описывает несуществующий проект
Самая частая проблема README — инструкция, которая работала полгода назад. Держите команды запуска рядом с конфигурацией и проверяйте их на чистом окружении хотя бы при изменении зависимостей.
Когда менять структуру
Не переносите каталоги только ради модного шаблона. Изменение оправдано, когда поиск файла занимает заметное время, CI постоянно запускает лишние задачи, общие библиотеки имеют неясных владельцев или релиз одного компонента блокирует другой.
Переносите структуру отдельным изменением, не смешивая его с бизнес-логикой. Сначала обновите пути сборки, тестов и импорта, затем переместите файлы, после чего отдельно проверьте CI, локальный запуск и упаковку артефактов. Историю Git легче читать, если переименование не сопровождается массовым переписыванием содержимого.
Что сделать дальше
Откройте корень своего репозитория и составьте карту из пяти строк: где исходный код, где тесты, где конфигурация поставки, где документация и где миграции. Для каждого каталога добавьте одно предложение о назначении. Затем запустите проверку на чистом окружении и измерьте не размер папок, а время от клонирования до первого успешного теста. Именно этот показатель покажет, стала ли структура понятнее, а не просто аккуратнее на вид.
Поиск источников: Реальные статьи и книги со ссылками, библиография по ГОСТ
Спросить за 15 ₽Источники: Git repository layout — официальная документация Git, About repositories — документация GitHub
Частые вопросы
Обязательно ли использовать именно папки src, tests и docs?
Нужно ли хранить папку .git в репозитории?
Можно ли коммитить файл .env?
Как поступить, если структура уже стала хаотичной?
Что выбрать для нескольких приложений: монорепозиторий или отдельные репозитории?
Нужно ли хранить в Git собранные файлы и Docker-образы?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.