Git для 1С: хранение конфигурации и CI/CD за 7 шагов

📅 Опубликовано 6 августа 2026 г.
Коротко: Git-хранение конфигурации 1С разворачивается за 7 шагов: выгрузка конфигурации в XML, инициализация репозитория с корректным .gitignore, синхронизация хранилища через gitsync, переход на ветки, автоматическая сборка CF/CFE на агенте, автотесты со статическим анализом и автообновление контуров. Базовый пайплайн на GitLab CI и OneScript команда из двух человек поднимает за 40–60 часов работы (наша оценка по проектам внедрения koderion.ru, 2025–2026 гг.), после чего выпуск релиза занимает 15–25 минут машинного времени вместо ручной процедуры на полтора часа.
- Git не заменяет хранилище сразу. На переходный период их держат параллельно: gitsync читает историю хранилища и превращает каждую помещённую версию в отдельный коммит с автором, датой и комментарием.
- Полная выгрузка в XML тяжёлая, инкрементальная — нет. По нашим замерам на конфигурации уровня 1С:УТ 11.5, платформа 8.3.24, SSD NVMe и 16 ГБ ОЗУ: полный
/DumpConfigToFiles— 25–45 минут, он же с ключом-update— 1–3 минуты. - Минимальный стек бесплатен. OneScript, vanessa-runner, gitsync, BSL Language Server распространяются по свободным лицензиям; платить нужно только за платформу, подписку ИТС и сервер сборки.
- Правило релиза одно: в продуктивную базу попадает только тот CF, который собран пайплайном из ветки master и прошёл синтаксический контроль, статический анализ и дымовые тесты.
- Окупаемость. Команда из 4 разработчиков, выпускающая 2 релиза в неделю, экономит на автоматизации сборки и обновления контуров порядка 20–30 часов в месяц ручных операций (расчёт ниже в таблице).
Чем Git отличается от хранилища конфигурации 1С?
Хранилище конфигурации (Configuration Repository) — это линейная история с блокировками: объект захвачен одним разработчиком, остальные ждут. Git — распределённая система с ветвлением и слиянием: параллельные задачи живут в отдельных ветках и объединяются через merge request с обязательным код-ревью. Для 1С разница не косметическая: она определяет, можно ли выпустить срочный хотфикс, пока в разработке лежит крупная доработка.
| Критерий | Хранилище конфигурации | Git-репозиторий |
|---|---|---|
| Параллельная работа | Захват объекта блокирует остальных | Ветки, слияние без блокировок |
| Хотфикс поверх релиза | Только через отдельное хранилище | Ветка от тега релиза за минуту |
| Код-ревью | Нет штатного механизма | Merge request с обсуждением строк |
| Откат изменения | Возврат к версии целиком | git revert отдельного коммита |
| Diff модуля | Штатное сравнение конфигураций | Построчный diff в любом инструменте |
| Интеграция с CI | Через выгрузку конфигуратором | Нативная: push запускает пайплайн |
| Порог входа команды | Низкий, знаком всем 1С-никам | Средний: нужны 1–2 дня обучения |
Какие инструменты понадобятся?
| Инструмент | Зачем нужен | Стоимость |
|---|---|---|
| OneScript (oscript) | Среда исполнения скриптов автоматизации на встроенном языке | Свободная лицензия |
| vanessa-runner (vrunner) | Обёртка над конфигуратором: сборка, загрузка, запуск тестов | Свободная лицензия |
| gitsync | Перенос истории из хранилища конфигурации в Git | Свободная лицензия |
| BSL Language Server | Статический анализ кода BSL, отчёт для SonarQube | Свободная лицензия |
| Vanessa Automation / xUnitFor1C | Сценарные и модульные тесты | Свободная лицензия |
| GitLab CE, Gitea + Jenkins | Сервер репозиториев и оркестратор сборки | Self-hosted, бесплатно |
| 1C:EDT | Разработка сразу в формате исходников | По лицензии платформы и подписке ИТС |
Шаг 1. Как выгрузить конфигурацию 1С в исходники?
Первое действие — получить текстовое представление конфигурации, которое Git умеет сравнивать построчно. Файл 1cv8.cf для этого не подходит: это бинарный контейнер, любой коммит с ним превращается в непрозрачный блоб на сотни мегабайт. Штатный механизм платформы — пакетный режим конфигуратора с ключом /DumpConfigToFiles.
# Полная выгрузка конфигурации в XML (иерархический формат)
"C:\Program Files\1cv8\8.3.24.1548\bin\1cv8.exe" DESIGNER \
/F "D:\bases\dev" /N "Разработчик" /P "" \
/DumpConfigToFiles "D:\repo\src\cf" -format Hierarchical \
/Out "D:\logs\dump.log" /DisableStartupDialogs
# Инкрементальная выгрузка: платформа обновляет только изменённые файлы
"C:\Program Files\1cv8\8.3.24.1548\bin\1cv8.exe" DESIGNER \
/F "D:\bases\dev" /N "Разработчик" /P "" \
/DumpConfigToFiles "D:\repo\src\cf" -update -force \
/Out "D:\logs\dump.log" /DisableStartupDialogs
Расширения выгружаются тем же ключом с параметром -Extension ИмяРасширения или -AllExtensions — держите их в отдельных каталогах src/cfe/ИмяРасширения. Иерархический формат (Hierarchical) предпочтительнее плоского: структура каталогов повторяет дерево метаданных, и в merge request сразу видно, какой справочник или документ затронут.
Обратная операция — /LoadConfigFromFiles — понадобится на шаге сборки. Проверьте её сразу: если конфигурация не собирается обратно из выгруженных файлов, дальше двигаться бессмысленно.
Шаг 2. Как создать репозиторий и настроить .gitignore?
Структура репозитория задаётся один раз и потом не переделывается без боли. Проверенный минимум:
src/cf/— исходники основной конфигурации;src/cfe/— исходники расширений, по каталогу на расширение;epf/— исходники внешних обработок и отчётов (в разобранном виде);tests/— модульные и сценарные тесты;tools/— скрипты сборки, настройки vrunner, JSON-конфигурации;docs/— регламент релиза, инструкция по развёртыванию.
git init
git config core.autocrlf ЛОЖЬ # 1С отдаёт CRLF, перекодировка ломает сравнение
git config core.quotepath ЛОЖЬ # кириллические имена файлов видны как есть
git lfs install # если храните дистрибутивы и большие бинарники
Содержимое .gitignore:
# Бинарные артефакты сборки
build/
*.cf
*.cfe
*.dt
*.epf
*.erf
# Служебные файлы платформы и EDT
ConfigDumpInfo.xml
.settings/
.metadata/
*.log
# Локальные настройки разработчика
tools/local.json
Отдельно про ConfigDumpInfo.xml: этот файл нужен для инкрементальной выгрузки, но в репозитории он порождает конфликты на каждом слиянии. Держите его в рабочем каталоге агента сборки и в личных каталогах разработчиков, а не в Git.
Кодировка исходников — UTF-8 с BOM, именно её отдаёт платформа. Настройте это на всех машинах команды и на агенте сборки, иначе каждый второй коммит будет содержать «изменение» всего файла целиком.
Шаг 3. Как перенести историю хранилища в Git через gitsync?
Резкий переход с хранилища на Git ломает работу команды. Правильная стратегия — период двойного ведения: разработчики продолжают помещать изменения в хранилище, а сервис gitsync раз в 10–15 минут вычитывает новые версии и превращает их в коммиты с сохранением автора, даты и комментария. Так команда получает историю в Git без единого дня простоя.
# Установка инструментов
opm install gitsync
opm install vanessa-runner
# Первичная выгрузка всей истории хранилища в Git
gitsync sync \
--tempdir "D:\gitsync\temp" \
--v8version 8.3.24.1548 \
"tcp://srv-repo/erp-store" "D:\repo\erp"
# Инкрементальная синхронизация по расписанию (задание планировщика)
gitsync sync --limit 50 "tcp://srv-repo/erp-store" "D:\repo\erp"
Соответствие пользователей хранилища и учётных записей Git задаётся файлом AUTHORS в корне репозитория — строками вида Иванов=Ivan Ivanov <i.ivanov@company.ru>. Без него все коммиты получат одного автора, и статистика по вкладу окажется бесполезной.
Первичная синхронизация большого хранилища с историей за несколько лет — операция на часы, а иногда и на выходные: на каждую версию платформа выполняет полноценную выгрузку конфигурации. Запускайте её на отдельной машине и не прерывайте.
Практическое правило: двойное ведение живёт 4–8 недель. Дальше хранилище переводится в режим «только чтение», а разработка полностью переезжает в ветки. Если оставить обе системы навсегда, команда неизбежно начнёт коммитить мимо синхронизации и история разъедется.
Шаг 4. Как организовать работу по веткам в 1С:EDT?
После переезда конфигуратор перестаёт быть точкой правды — ей становится репозиторий. Для полноценной работы с ветками удобнее 1C:EDT: она хранит проект в формате исходников, а Git-клиент встроен в среду. Команды, оставшиеся на конфигураторе, работают через связку «локальная база + vrunner»: перед началом задачи разработчик переключает ветку и загружает конфигурацию из файлов в свою базу.
# Разработчик берёт задачу
git checkout master
git pull
git checkout -b feature/ERP-1487-vozvrat-ot-klienta
# Загрузка исходников ветки в локальную базу и обновление конфигурации БД
vrunner init-dev --src src/cf --ibconnection "/F./build/ib"
# После правок — выгрузка изменений обратно в файлы
vrunner decompile --src src/cf --ibconnection "/F./build/ib"
git add src/cf
git commit -m "ERP-1487: возврат от клиента — контроль количества по документу продажи"
git push -u origin feature/ERP-1487-vozvrat-ot-klienta
Модель ветвления для 1С обычно упрощённая: master — то, что стоит в продуктиве; develop — накопительная ветка спринта; feature/* — задачи; hotfix/* — срочные исправления от тега релиза. Правило именования веток по номеру задачи из трекера окупается сразу: по коммиту всегда понятно, зачем изменение внесено.
Отдельная договорённость нужна по конфликтам в формах и макетах. XML-представление управляемой формы плохо поддаётся ручному слиянию, поэтому одну форму в одном спринте правит один разработчик — это дисциплина планирования, а не техническое ограничение. Так же мы разводим работы, когда параллельно идут доработки складского блока: типовые ошибки настройки адресного хранения обычно затрагивают те же формы подбора и документы отбора товаров.
Шаг 5. Как автоматически собирать CF и CFE на агенте?
Сборка — это обратное преобразование: из XML-исходников платформа собирает конфигурацию и выгружает бинарный файл поставки. Задача агента — сделать это в чистой временной базе, без участия человека.
# 1. Создание пустой файловой базы
"C:\Program Files\1cv8\8.3.24.1548\bin\1cv8.exe" CREATEINFOBASE "File=D:\build\ib"
# 2. Загрузка конфигурации из исходников
"C:\Program Files\1cv8\8.3.24.1548\bin\1cv8.exe" DESIGNER \
/F "D:\build\ib" /LoadConfigFromFiles "D:\repo\src\cf" \
/UpdateDBCfg -Dynamic- /Out "D:\logs\build.log"
# 3. Синтаксический контроль всех модулей
"C:\Program Files\1cv8\8.3.24.1548\bin\1cv8.exe" DESIGNER \
/F "D:\build\ib" /CheckModules -ThinClient -Server -ExternalConnection \
/Out "D:\logs\check.log"
# 4. Выгрузка файла поставки
"C:\Program Files\1cv8\8.3.24.1548\bin\1cv8.exe" DESIGNER \
/F "D:\build\ib" /DumpCfg "D:\build\artifacts\1cv8.cf" \
/Out "D:\logs\dump.log"
Начиная с платформы 8.3.20 те же операции доступны через утилиту ibcmd, которая не требует запуска графической оболочки конфигуратора и работает заметно стабильнее в контейнерах и на серверах без GUI. Ключевые команды — ibcmd infobase config import (загрузка исходников), ibcmd infobase config apply (обновление конфигурации БД) и ibcmd infobase config save (выгрузка CF).
Важная деталь: агент сборки должен иметь лицензию платформы. Дешёвый вариант — программная лицензия на сервер сборки или свободный сеанс из клиентских лицензий; если сборка падает с ошибкой «Не обнаружена лицензия», в 9 случаях из 10 дело в том, что агент запущен под сервисной учётной записью без доступа к каталогу лицензий.
Шаг 6. Как прогонять тесты и контроль качества на каждый merge request?
Сборка, которая просто «собралась без ошибок», ничего не гарантирует: синтаксический контроль ловит опечатки, но не ловит сломанную логику расчёта скидки или неверную проводку. Поэтому после шага сборки в конвейер добавляется два независимых этапа — автотесты и статический анализ. Тесты запускаются в той самой временной базе, что создал агент: платформа стартует в режиме предприятия с ключом /RunModeOrdinaryApplication и внешней обработкой-раннером (vanessa-automation.epf для сценарных тестов или yaxunit.epf для модульных), а результат выгружается в JUnit-XML, который GitLab и Jenkins умеют показывать прямо в интерфейсе merge request.
Модульные тесты на YAxUnit живут в самой конфигурации — в подсистеме, которая не попадает в поставку. Выглядит это так:
#Область СлужебныйПрограммныйИнтерфейс
Процедура ИсполняемыеСценарии() Экспорт
ЮТТесты
.ДобавитьТестовыйНабор("РасчётСкидок")
.ДобавитьСерверныйТест("СкидкаНеПревышаетПорог")
.ДобавитьСерверныйТест("СкидкаНеПрименяетсяКУценённымТоварам");
КонецПроцедуры
#КонецОбласти
#Область ТестыСервер
Процедура СкидкаНеПревышаетПорог() Экспорт
Заказ = ТестовыеДанные.СоздатьЗаказПокупателя(10000);
РазмерСкидки = РасчётСкидокСервер.РассчитатьСкидку(Заказ);
ЮТест.ОжидаетЧто(РазмерСкидки, "Размер скидки")
.Заполнено()
.МеньшеИлиРавно(Заказ.СуммаДокумента * 0.3);
КонецПроцедуры
#КонецОбласти
Параллельно исходники проверяет BSL Language Server: он читает тот же каталог src/cf, что лежит в репозитории, и отдаёт отчёт в формате SonarQube или Code Climate. Практический совет — не включать все диагностики сразу. На зрелой конфигурации первый запуск даёт тысячи замечаний, команда пугается и отключает анализ целиком. Начните с блокирующих: пустые блоки Попытка … Исключение, обращение к Метаданные() в цикле, отсутствие транзакции при записи набора документов. Правило «новый код не добавляет замечаний» (режим анализа только изменённых строк) работает лучше, чем попытка разом починить накопленный долг.
test:
stage: test
script:
- powershell ./ci/run-yaxunit.ps1 -Ib "D:\build\ib" -Report "junit.xml"
artifacts:
reports:
junit: junit.xml
sonar:
stage: test
script:
- bsl-language-server --analyze --srcDir src/cf --reporter sonarqube
- sonar-scanner -Dsonar.projectKey=erp -Dsonar.qualitygate.wait=ИСТИНА
Шаг 7. Как автоматически доставлять обновление на тестовый и рабочий контур?
Последний шаг превращает CI в CD. Артефакт 1cv8.cf, собранный и проверенный на предыдущих этапах, доставляется в базу-приёмник: на тестовый контур — автоматически при каждом мерже в develop, на рабочий — только по ручному подтверждению из ветки master. Отличие рабочего контура не в командах, а в обвязке: перед обновлением обязательны резервная копия средствами СУБД (не /DumpIB — на базе в сотни гигабайт выгрузка в DT идёт часами) и корректное завершение сеансов через блокировку, иначе /UpdateDBCfg упадёт с ошибкой «Операция не может быть выполнена: имеются активные сеансы».
Процедура ЗапретитьВходПользователей(ДлительностьМинут, КодРазрешения) Экспорт
Блокировка = Новый БлокировкаСеансов();
Блокировка.Начало = ТекущаяДатаСеанса() + 60;
Блокировка.Конец = Блокировка.Начало + ДлительностьМинут * 60;
Блокировка.КодРазрешения = КодРазрешения;
Блокировка.Сообщение = "Идёт обновление конфигурации. Повторите вход через "
+ ДлительностьМинут + " мин.";
(удалить строку — свойство только для чтения)
УстановитьБлокировкуСеансов(Блокировка);
КонецПроцедуры
Дальше агент подключается к базе с параметром /UC (тот самый код разрешения), загружает файл поставки как обновление и применяет его к базе данных. После обновления блокировка снимается, а конвейер помечает релиз тегом — по тегу всегда видно, какой коммит сейчас работает в продуктиве. Откат в этой схеме — не «восстановить бэкап и забыть», а обычный деплой предыдущего тега; бэкап остаётся страховкой на случай, когда обновление уже успело изменить структуру таблиц.
# 1. Обновление конфигурации базы-приёмника
"C:\Program Files\1cv8\8.3.24.1548\bin\1cv8.exe" DESIGNER \
/S "srv-app:1541\erp_test" /N "deploy" /P "%DEPLOY_PWD%" /UC "DeployKey2026" \
/UpdateCfg "D:\build\artifacts\1cv8.cf" /UpdateDBCfg -Server \
/Out "D:\logs\deploy.log" /DisableStartupMessages
# 2. Снятие блокировки и запуск отложенных обработчиков
"C:\Program Files\1cv8\8.3.24.1548\bin\1cv8.exe" ENTERPRISE \
/S "srv-app:1541\erp_test" /N "deploy" /P "%DEPLOY_PWD%" /UC "DeployKey2026" \
/Execute "D:\ci\ЗавершитьОбновление.epf" /Out "D:\logs\post-deploy.log"
Типовые конфигурации на БСП после смены версии требуют отработки обработчиков обновления информационной базы — на рабочем контуре это делается в монопольном режиме первым запуском под администратором, поэтому шаг 2 в примере запускает внешнюю обработку, которая вызывает ОбновлениеИнформационнойБазы.ВыполнитьОбновлениеИнформационнойБазы() и пишет в лог результат. Если этот вызов не автоматизировать, пользователи придут утром в базу, которая просит «подождать завершения обновления» неопределённое время.
Найдите специалиста для решения этой задачи на koderion.ru