Пятничный тупик: проверяем слияние коротких веток 1С в git
Разработка - Инструментарий разработчика
Файлы
ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.
Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний
Оформите подписку на компанию для решения рабочих задач
Оформить подписку и скачать решение со скидкойВы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
Команда проекта ведёт конфигурацию 1С в git и желает выполнять ежевечерние слияния веток проекта, не накапливая изменения до недельного слияния. Есть опасение, что при частых слияниях выгрузка конфигурации в XML-файлы (команда /DumpConfigToFiles) будет регулярно давать конфликты и каждое слияние потребует разбора вручную. Хранилище конфигурации здесь не поможет: ветвление в нём не предусмотрено, поэтому задача решается только средствами git. Для её решения я написала tbd_check.py: пробным слиянием он выявляет конфликты до их возникновения, описывает их в терминах объектов 1С (модуль, форма, состав конфигурации, служебный файл) и предлагает способ разбора для каждого вида. По истории репозитория он же определяет продолжительность жизни веток и файлы, наиболее часто попадающие в конфликт, и формирует .gitattributes, одна строка которого устраняет самый частый конфликт.
При частых слияниях конфликты повторяются в двух местах: в служебном файле ConfigDumpInfo.xml и в списке объектов конфигурации Configuration.xml. Первый исключается настройкой git, второй разбирается целыми вставками. Построчное объединение версий из двух сливаемых веток нарушило структуру всех трёх видов файлов, на которых я его проверила. Эти правила следует согласовать до первого ежедневного слияния. Время разбора конфликтов человеком я не измеряла.
- Платформа переписывает ConfigDumpInfo.xml при каждой выгрузке: три выгрузки подряд без единой правки дали новые версии у всех 244 объектов в нём. Разбирать этот файл вручную не требуется: достаточно строки
ConfigDumpInfo.xml merge=oursв .gitattributes и настройки драйвера git. - Построчное объединение версий файла из двух сливаемых веток (
git merge-file --union) нарушило структуру всех трёх видов файлов, на которых я его проверила: XML-файла описания перечисления, Configuration.xml и модуля. Конфликты в выгрузке разбираются целыми вставками. - Число пересечений у коротких веток то же, они распределяются по дням: семь конфликтов по одному файлу вместо одного слияния с четырьмя конфликтными файлами.
- Если у двух разработчиков по-разному настроен перевод строк (
core.autocrlf), правка одной строки модуля превращается в конфликт на 84 строки. Строка* -textв .gitattributes устраняет эту причину. - На учебной конфигурации сборка main в чистую базу заняла 16,6 с, сухое слияние около 3 с. Это машинное время, разбор конфликтов человеком сюда не входит.
Короткие ветки в 1С возможны, если выгрузка лежит в git и команда до первого слияния договорилась, что делать с ConfigDumpInfo.xml, как разбирать Configuration.xml и формы и как проверять main после каждого слияния.
Для кого: разработчики и ведущие 1С-команд, которые ведут или собираются вести конфигурацию в git и хотят понять, выдержит ли их выгрузка ежедневные слияния.
- Стенд
- Есть ли ветки в хранилище конфигурации
- Опыт: десять правок двумя способами
- ConfigDumpInfo.xml: конфликт в каждом из 11 параллельных слияний
- Как разбирать остальное: целыми вставками
- Переводы строк: конфликт из-за настройки git
- Что делает инструмент
- Сколько это стоит по времени
- Пределы
- Что проверить в репозитории своего проекта
- Файлы к статье
- Итог
Чтобы ответить на это опасение измерением, я поставила опыт на учебной конфигурации «Нано-УТ 2.0». Два разработчика внесли по 10 одинаковых правок двумя способами: с одним слиянием в конце и со слиянием после каждой правки. После каждого слияния main загружался в чистую базу и проверялся; всего выполнено 22 слияния. Далее описаны стенд, ход опыта, источники конфликтов и способы их разбора.
Стенд
| Условие | Значение |
|---|---|
| Платформа | 1С:Предприятие 8.3.27.2130 x86, пакетный Конфигуратор (DESIGNER), файловые базы |
| Конфигурация | «Нано-УТ 2.0», учебная; выгрузка платформой: 270 файлов, из них 68 Form.xml, 57 BSL-модулей |
| Контроль версий | git 2.56.0, новый репозиторий, первый коммит - чистая выгрузка |
| Инструмент | tbd_check.py, Python 3.12.10, только стандартная библиотека |
| Компьютер | Windows 11 Pro, Intel Core i5-2400, 7,9 ГБ ОЗУ, SATA SSD |
Есть ли ветки в хранилище конфигурации
Прежде чем переходить к git, следовало убедиться, что ветвление отсутствует в хранилище конфигурации. Справку 1cv8 DESIGNER /? сборка 8.3.27.2130 не выводит, поэтому имена команд были извлечены скриптом из 1cv8.exe и библиотек каталога bin. Найдено 23 команды и параметра хранилища, все начинаются с ConfigurationRepository:
| Что есть | Команды |
|---|---|
| создание и подключение | Create, BindCfg, UnbindCfg |
| захват и помещение | Lock, Unlock, Commit |
| получение и выгрузка | UpdateCfg, DumpCfg |
| история и метки | Report, SetLabel |
| пользователи и обслуживание | AddUser, CopyUsers, ClearCache, ClearGlobalCache, ClearLocalCache, OptimizeData |
Слова Branch в этом списке нет. Хранилище было создано из командной строки, затем получен отчёт /ConfigurationRepositoryReport: одна линия версий с номером, автором, датой и комментарием, поля «ветка» в нём нет. Окна хранилища в Конфигураторе я не открывала, поэтому вывод относится к пакетному режиму.
Практический вывод: в хранилище можно часто помещать небольшие изменения, и по смыслу это близко к trunk-based разработке. Ветка на задачу со слиянием в конце в этом опыте возможна только в git, на XML-выгрузке конфигурации; далее весь опыт выполняется на ней.
Опыт: десять правок двумя способами
Два разработчика, роли обоих исполняла я, внесли по 10 правок. Пересечения заложены такие, какие встречаются в работе: оба дописывают функцию в один общий модуль; один добавляет реквизит документа, другой правит форму этого же документа; оба добавляют справочник, общий модуль и константу, что изменяет Configuration.xml; оба добавляют значение в одно перечисление.
Каждая правка вносилась в текст выгрузки, затем выгрузка загружалась в базу командой /LoadConfigFromFiles и выгружалась обратно командой /DumpConfigToFiles. Этот шаг необходим: служебные файлы изменяет платформа, и именно они дают больше всего конфликтов, поэтому без него опыт не воспроизводил бы работу команды.
- Модель A. Каждый разработчик накапливает 10 правок в своей ветке десять дней, затем обе ветки сливаются в main.
- Модель B. После каждой правки ветка разработчика сливается в текущий main: 10 раундов, 20 слияний.
После каждого слияния main загружался в чистую базу, затем выполнялись /UpdateDBCfg и /CheckModules -Server -ThinClient.
| Модель | Слияний | С конфликтом | Конфликтных файлов | Участков | Строк в маркерах |
|---|---|---|---|---|---|
| A: слияние в конце | 2 | 1 | 5 | 30 | 598 |
| B: слияние после каждой правки | 20 | 10 | 17 | 240 | 5540 |
| A без ConfigDumpInfo.xml | 2 | 1 | 4 | 6 | 50 |
| B без ConfigDumpInfo.xml | 20 | 7 | 7 | 7 | 38 |
По первым двум строкам короткие ветки выглядят хуже: в модели B строк в конфликтах почти в десять раз больше. Однако почти все эти строки приходятся на один файл, ConfigDumpInfo.xml. Без него картина иная: у длинных веток одно крупное слияние с четырьмя конфликтными файлами (модуль, форма, состав конфигурации, перечисление), у коротких семь слияний, в каждом ровно один файл и один участок.
По числу конфликтных файлов короткие ветки уступают: 7 против 4. Пересечения те же, они лишь распределены по дням. Средний конфликт при этом меньше: 5,4 строки на файл против 12,5. Оговорка: в модели B изменения сливались в том же смоделированном раунде; как такой режим отразится на работе живой команды, я не проверяла.

premerge перед слиянием длинной ветки: конфликты в терминах объектов 1С
ConfigDumpInfo.xml: конфликт в каждом из 11 параллельных слияний
ConfigDumpInfo.xml хранит версии всех объектов выгрузки. Одна и та же конфигурация была трижды загружена и выгружена без единой правки. Версии совпали у 0 объектов из 244, остальные файлы не изменились. Отсюда расхождение служебных версий в ветках: платформа переписывает этот файл при каждой выгрузке. Другие режимы выгрузки и другие версии платформы здесь не проверялись. В опыте файл конфликтовал в 11 слияниях из 11, где изменения вносились в обеих сливаемых ветках, по 546–554 строки в маркерах.
Затем проверено, как платформа обрабатывает этот файл при полной загрузке. Рассмотрены пять вариантов: версия первого разработчика, версия второго, файл с маркерами конфликта внутри, построчное объединение двух версий и удалённый файл. Во всех пяти /LoadConfigFromFiles вернул код 0, /CheckModules ошибок не обнаружил, следующая выгрузка дала тот же набор объектов. Следовательно, на проверенной платформе содержимое ConfigDumpInfo.xml на полную загрузку не влияет; следующая выгрузка создаёт его заново.
Поэтому разбирать его вручную не требуется. Достаточно двух действий:
Вторая строка обязательна: без неё атрибут не действует. Проверены все три состояния: конфликтных файлов было 5 без атрибута, 5 с атрибутом без драйвера и 4 с атрибутом и драйвером. Возможен и другой путь: не хранить файл в git. Полная загрузка без него проходит; инкрементальную выгрузку -update без него я не проверяла.
Как разбирать остальное: целыми вставками
При конфликте в XML-файле описания объекта (перечисления, документа, формы) первое побуждение состоит в том, чтобы объединить построчно версии файла из двух сливаемых веток, то есть оставить все строки обеих (git merge-file --union или аналогичная команда в клиенте git). Этот способ проверен на трёх видах файлов, и все три оказались непригодны к загрузке:
| Файл | Что вышло после построчного объединения |
|---|---|
| XML-файл описания перечисления | загрузка, код 1: «Ошибка разбора XML» |
| Configuration.xml | загрузка, код 1: «Дублирование имени объекта метаданных» |
| модуль .bsl | /CheckModules, код 101: «Ожидается ключевое слово КонецФункции» |
Работает другой способ: сохранить целиком вставку каждой из двух веток, по одному разу, и сразу проверить main загрузкой в базу. Так выполнены все 22 слияния. Первую попытку слить модель A я выполнила через --union, получила несобираемый main и повторила слияние заново; это отмечено в журнале опыта.
Configuration.xml конфликтовал в 4 слияниях из 4, где оба разработчика добавляли объект одного вида: справочник, общий модуль, константу. Новые объекты дописываются в один и тот же список, и git видит две разные вставки в одно место. В проверенных слияниях конфликт занимал по 8 строк. Построчное объединение дало повторные имена и отказ загрузки.
У форм есть особенность. В контрольной форме оба разработчика добавили элементы с одинаковым очередным id, и после слияния образовались повторы. Платформа такую выгрузку загрузила без ошибок. Как поведёт себя эта форма в клиенте, я не проверяла, поэтому инструмент после слияния предупреждает о повторах id.

Сборка main после последнего слияния модели B: загрузка, обновление базы, проверка модулей
Переводы строк: конфликт из-за настройки git
Выгрузка стенда содержит .bsl и .xml в UTF-8 с BOM и переводами строк CRLF. В проверенном сценарии первый коммит при core.autocrlf=true нормализовал строки до LF, а коммит другой стороны при false сохранил CRLF. Правка одной строки модуля дала конфликт на весь файл: 84 строки внутри маркеров. С * -text в .gitattributes или с *.bsl text eol=crlf конфликта не было. Первый вариант проще: git хранит файлы выгрузки в том виде, в каком их записала платформа.
Что делает инструмент
Команды history и premerge не изменяют рабочую копию, индекс и ссылки репозитория: тест сравнивает HEAD, ссылки, индекс, git status и неотслеживаемые файлы до и после. Команда gitattributes --write может создать новый .gitattributes, но отказывается перезаписывать существующий, даже ещё не добавленный в git. Платформа 1С инструменту не нужна, нужен git 2.38 или новее.
| Команда | Что делает |
|---|---|
premerge <репозиторий> <ветка> |
сухое слияние ветки в main через git merge-tree: конфликты в терминах объектов 1С (модуль, форма, состав, служебный файл, описание объекта) и что делать с каждым видом; код 1, если конфликты есть |
history <репозиторий> |
переигрывает слияния main: время жизни веток, частота слияний, файлы, чаще всего попадавшие в конфликт, ветки, ещё не влитые в main |
gitattributes <репозиторий> |
предлагает .gitattributes для выгрузки по её фактическому составу (BOM, переводы строк); пишет файл только с --write |
Прогноз premerge сверен с фактом: перед каждым из 22 слияний опыта он назвал те же конфликтные файлы и то же число строк, что затем показал git merge. Ненулевой код возврата позволяет включить его в сборочную линию перед слиянием запроса.

history по репозиторию модели B
Сколько это стоит по времени
| Операция | Время |
|---|---|
| /LoadConfigFromFiles Нано-УТ | 10,1 с (медиана из 40) |
| /DumpConfigToFiles Нано-УТ | 5,3 с (медиана из 40) |
| сборка main: чистая база, загрузка, /UpdateDBCfg, /CheckModules | 16,6 с (медиана из 22) |
| premerge | 3,1 с |
| history по 20 слияниям | 20,4 с |
На конфигурации такого размера ежедневное слияние с проверкой main укладывается в полминуты машинного времени. На крупной типовой конфигурации загрузку и проверку я не измеряла. Эту величину следует измерить до перехода: от неё зависит, будет ли команда проверять main после каждого слияния или раз в день. history расходует около секунды на слияние; для длинной истории предусмотрен ключ --max-merges (по умолчанию 200).
Пределы
- Правки и календарь коммитов задала я. Это модель двух разработчиков, живой команды в опыте нет, и выводы о частоте конфликтов относятся к этому набору правок.
- Одна учебная конфигурация на 270 файлов. На больших типовых, в формате EDT и для расширений опыт не повторялся.
- Ветвление в хранилище проверено по командной строке платформы, окна Конфигуратора я не открывала.
- Клиентское приложение не запускалось: как ведут себя формы с повторяющимися
idэлементов, неизвестно.
Что проверить в репозитории своего проекта
- Поместите в корень репозитория проекта файл .gitattributes со строками
* -textиConfigDumpInfo.xml merge=ours, в каждом клоне выполнитеgit config merge.ours.driver true. Командаtbd_check.py gitattributesпредложит состав файла по вашей выгрузке. - Выполните
tbd_check.py historyдля репозитория проекта: он покажет, сколько живут ветки и какие файлы чаще всего попадают в конфликты. - Перед слиянием длинной ветки запустите
tbd_check.py premerge: он покажет конфликты до слияния и вид каждого. - Согласуйте в команде правило: конфликты в XML-файлах выгрузки разбираются целыми вставками, построчное объединение версий из двух веток не применяется.
- Измерьте время сборки main в чистую базу на конфигурации проекта. Если оно составляет минуты, проверяйте main не реже раза в день.
Файлы к статье
Инструмент trunk-28-1-tool.zip. tbd_check.py с командами history, premerge и gitattributes, 38 тестов на временных git-репозиториях и README с запуском, кодами возврата и пределами. Отчёты выходят в двух видах: report.md для человека и report.json для сборочной линии. Тесты из чистой распаковки:
Архив к статье trunk-28-1-companion.zip. Заполненный чек-лист перехода на короткие ветки с пометкой, чем проверен каждый пункт; предложенный .gitattributes с пояснением каждой строки; отчёты history и premerge из опыта; скрипты стенда, которые повторяют обе модели, сборку main и пробы с ConfigDumpInfo.xml; команды повторения по шагам.
Расширенная PDF-копия статьи (28 страниц) входит в тот же архив. В ней полный текст статьи и восемь приложений: заполненный чек-лист перехода, команды повторения опыта по шагам, полные таблицы конфликтов по каждому из 22 слияний, таблица сборки main, сравнение прогноза premerge с фактом, полные отчёты инструмента и журналы прогонов. Она нужна, чтобы прочитать статью без сайта и проверить приведённые числа по первичным данным.
Итог
Короткие ветки в этом опыте велись в git, на XML-выгрузке конфигурации; возможности интерфейса хранилища я не проверяла. При двух разработчиках и 22 слияниях main собирался каждый раз, но только при разборе конфликтов целыми вставками. Построчное объединение нарушало структуру файла описания перечисления, состава конфигурации и модуля.
Главным источником конфликтов оказался ConfigDumpInfo.xml: он конфликтовал во всех 11 слияниях с параллельными изменениями, и ни один из пяти вариантов его содержимого на полную загрузку не повлиял. Строка в .gitattributes и настройка драйвера git исключают его из разбора. Без него короткие ветки дали 7 конфликтных файлов против 4 у длинных, по одному файлу за слияние, в среднем 5,4 строки внутри маркеров против 12,5. Инструмент определил состав конфликтов заранее во всех 22 слияниях.
Вступайте в нашу телеграмм-группу Инфостарт