Синхронизация проекта 1C:EDT с хранилищем конфигурации

09.07.26

Разработка - Групповая разработка (Git, хранилище)

Синхронизируйте свой проект EDT с хранилищем конфигурации так же легко, как в git клиенте. По кнопке Pull в проект EDT подтягиваются изменения из хранилища, по кнопке Push ваш коммит из git репозитория проекта EDT улетает в хранилище конфигурации.

Введение

В этой публикации я расскажу про механизм синхронизации с хранилищем, который позволяет мне легко отправлять свои коммиты из репозитория проекта EDT в хранилище конфигурации и получать коммиты из хранилища конфигурации в проект EDT. В разделе "Рабочий процесс" покажу, какой "git-storage-flow" принят при работе с синхронизацией. В разделе "Технический процесс" вкратце расскажу, что происходит под капотом, когда пользователь нажимает одну из двух кнопок Pull/Push. В разделе "Сценарий использования" приведу свой сценарий работы, от настройки до первого коммита в хранилище. Здесь не будет пересказа инструкции по работе в 1C:EDT, только необходимый минимум. Затем раздел "Доработка и сопровождение. В заключительном разделе "Замечания" подсветил замеченные мной вещи, которые не поддаются устранению, либо это устранимые замечания, о них мне известно и запланировано их устранение.

Кто желает сразу установить, настроить и начать использовать, может сразу ознакомиться с разделами:

  1. Компоненты
  2. Как это выглядит
  3. Рабочий процесс
  4. Сценарий использования

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

 

Компоненты

Непосредственно за саму синхронизацию отвечают два компонента - плагин для EDT и осенняя поделка для работы с проектами EDT. Сортировка объектов лишь как вишенка на тортик, без него композиция выглядит незавершенной.

 

Как это выглядит

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

Две кнопки Pull/Push как в git клиенте:

 
 картинка

 

Получение изменений из хранилища:

 
 картинка

 

Отправление изменений в хранилище:

 
 картинки

 

Для кого это всё

  1. Для меня. Использую сам и делюсь идеей.
  2. Для той прогрессивной малой части разработчиков, которая присутствует в каждой команде разработки.
    Что делать, когда в типичной команде разработки 10-50 разработчиков, из которых 1-2 хотят попробовать EDT, а конфигурация в хранилище?
  3. Для матёрой команды EDTшников, которые уже и забыли, что такое хранилище конфигурации.
    Пример. Все разработчики заняты на срочных задачах. Прибегает босс, говорит тимлиду, что, кровь из носа, нужно успеть сделать такую-то фичу к такой-то дате, иначе всё пропало, придут конкуренты и всё отожмут. Тимлид отвечает - у нас нет свободных рук, Вася занят на проекте Х, если не успеет, придут желтые конкуренты и всё отожмут, Петя также, там красные конкуренты, у Светы - синие. Все при деле. Босс решает привлечь команду сторонних разработчиков, которые 100% успеют к этой дате, так как у них уже есть накопленный опыт и экспертиза в этом деле, но... они работают в хранилище и знать не знают про эти ваши EDT. Тимлид разворачивает на своей стороне хранилище, запускает туда стороннюю команду, а своя команда по возможности мониторит/кодревьюит стороннюю разработку в... EDT, да, делают это не покидая EDT, даже могут вносить свои корректировки, не покидая EDT.
  4. Для поддержания текущего devops процесса. Хранилище может занимать своё место на пути от первого коммита и до релиза в продуктив. Хранилище может использоваться для подготовки файла поставки. Могут быть какие-нибудь предрелизные хранилища, в которых собираются протестированные, стабильные коммиты. Даже если вся команда перешла на EDT, стоит ли ломать существующий сложный devops комбайн? В каком-то случае стоит, так как это будет давать какие-то очевидные просчитанные бенефиты, но отказ от прежней модели может занять продолжительное время, а пока нужно поддержать текущую модель.

Это навскидку, что сразу приходит на ум при ответе на вопрос "Зачем это всё?". Уверен, читатели могут привести ещё 100500 случаев, когда синхронизация EDT с хранилищем была бы не лишней.

 

Рабочий процесс (workflow)

Вообще сама идея берет начало из статьи Особенности использования репозитория Git для хранения технического проекта.

Настоятельно рекомендую ознакомиться с этой статьей и понимать картинку ниже:

 

 

Принятая концепция:

Дано: конфигурация версионируется в хранилище конфигурации. Каждый разработчик, дорабатывающий эту конфигурацию в EDT, разворачивает у себя свой личный git репозиторий проекта этой конфигурации.

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

  1. Ветка master - это отражение хранилища конфигурации в репозитории проекта EDT. Грубо говоря, это как удаленная ветка origin, но синхронизирующаяся только в одном направлении. В ветку master НЕ рекомендуется коммитить, за редким исключением при инициализации репозитория проекта. Ветка master служит для аккумуляции коммитов из хранилища.
  2. Доработки ведутся в отдельных feature ветках. Когда выполнена доработка, в feature ветку вливается актуализированная ветка master и затем коммит слияния (merged branch) отправляется в хранилище. Для тех кто работал по git flow этот процесс знаком.

Жизненный цикл feature ветки представляет такой граф (ветка master голубого цвета, feature ветка - желтого):

 

 

В самом простом виде граф будет таким:

 

 

Т.е. от master делается ответвление и затем результат отправляется в хранилище, а из хранилища уже попадает обратно в master.

Можно добавить сколько угодно промежуточных веток - develop, test, fix и т.д., это зависит уже от вашего рабочего процесса, но ветка master жестко завязана на отражение хранилища конфигурации, потому что master это master - это точка публикации доработок всеми разработчиками.

 

Технический процесс

 

Операция получения изменений из хранилища

  1. Плагин EDT проксирует выполнение команды в консольное приложение jeweltools, вызывая команду v8storage pull.
  2. Выполняется проверка на пустоту индекса гита.
    1. Если присутствуют незафиксированные изменения, требуется их зафиксировать или застешить.
  3. Переключение на ветку master.
  4. jeweltools призывает gitsync с включенным плагином edtExport, запускается импорт коммитов хранилища.

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

 

Операция отправления изменений в хранилище

  1. Выполняется инкрементальное обновление приложения, связанного с разрабатываемой конфигурацией.
  2. Выгрузка конфигурации актуализированного приложения в cf файл.
  3. Плагин EDT проксирует выполнение команды в консольное приложение jeweltools, вызывая команду v8storage push с переданным идентификатором коммита предка.
  4. Выполняется проверка на пустоту индекса гита.
    1. Если присутствуют незафиксированные изменения, требуется их зафиксировать или застешить.
  5. Оптимистическая блокировка.
    Сравниваются версии хранилища - версия ранее полученных изменений должна совпадать с актуальной версией в хранилище. Если версии не совпадают, возникает ошибка, требуется актуализировать master.
  6. Определяется идентификатор коммита HEAD.
  7. Определяется таблица измененных объектов между коммитами HEAD и его предком, который был указан пользователем.
  8. Формируется список объектов для их захвата в хранилище по данным таблицы измененных объектов.
  9. Формируются настройки слияния - правила сопоставления (Conformities) и правила объединения (Objects). Конечно же слияние в хранилище происходит строго по идентификаторам объектов. В настройках слияния указана сортировка из хранилища.
  10. Далее управление передается v8runner - захватываются объекты, заливается в хранилище выгруженная ранее конфигурация и коммитится под сообщением, указанным пользователем.
    1. В момент захвата объектов в хранилище, возникает нативная пессимистическая блокировка. Если объекты удалось захватить явно, значит мы наложили жесткую блокировку, никто теперь нам не помешает поместить свои изменения.
    2. После успешного захвата объектов, но до коммита, повторяется оптимистическая блокировка. Если версии по-прежнему совпадают - нам горит зеленый свет на слияние в хранилище.
      Примечание - мы захватили объекты, мы их получили уже актуальными, зачем еще раз проверять версии? Когда я говорю "оптимистическая объектная блокировка", то я подразумеваю всю конфигурацию как один объект, если внутри этого объекта что-то изменилось, значит мы работаем с устаревшим объектом, его состояние изменилось. Например, мы захватили общий модуль, в методе которого в запросе сослались на ресурс регистра сведений. И так получилось, что пока мы коммитили в хранилище, кто-то в эту секунду успел залить в хранилище удаление этого ресурса у регистра. Мы этот регистр не захватываем, мы его не получаем актуальным, мы коммитим только общий модуль, очевидно в этом случае наша доработка потеряла консистентность, требуется согласование нашей доработки с новым контекстом. Поэтому и повторяется здесь оптимистическая блокировка по версии объекта.

Если сработала блокировка и требуется актуализировать master, то после получения свежих коммитов из хранилища, зачастую вообще не возникает конфликтов при слиянии свежего мастера в фича-ветку. Здесь мы имеем дело с преимуществом Git перед хранилищем. Git сравнивает построчно, а хранилище пообъектно, соответственно Git эскалирует на уровень пользователя только тот неразрешимый конфликт, где была дважды изменена одна и та же строка, а это достаточно редкое событие, поэтому и не так часто появляется окно сравнения-объединения в EDT, а если оно и возникает, то только по какой-то мелочи. В общем, актуализация фича-ветки свежим мастером это быстрый и порой незаметный для пользователя процесс.

 

Скорость выполнения обеих операций

 

За получение коммитов из хранилища отвечает gitsync, понятный, быстрый, стабильный инструмент, проверенный временем. Чтобы добиться максимальной скорости, требуется включить плагин increment. Кроме этого, субъективно, считаю, что плагин tool1CD добавляет пару попугаев к скорости. Понятно, что там выгружается конфа в файлики, они конвертируются в формат EDT, не быстро это, но в целом мне хватает скорости. Зачастую коммиты прилетают в инкрементальном режиме, а это быстро. Когда же возникает полная выгрузка (Full dump), то приходится немного подождать, на конфигурации 1С:Документооборот (2,5 млн строк кода) минут 5-7 в зависимости от ресурсов, на ЕРП конечно подольше. Но, полный дамп возникает редко и однократно (без серий), поэтому можно потерпеть. Полный дамп возникает в случаях когда: 1. Удаляется объект - справочник, модуль, измерение, ресурс, реквизит и т.п. 2. Переименовывается объект - справочник, модуль, измерение, ресурс, реквизит и т.п. А это достаточно редкие события.

Отправка в хранилище, несмотря на лютый комбайн под капотом, образно, выполняется немного дольше, чем мгновенно. Но если разобраться, в используемых механизмах нет ничего, что могло бы значительно притормозить отправку. Такая высокая скорость была достигнута использованием механизмов EDT, Git и консольных утилит конфигуратора. В EDT был задействован механизм инкрементального обновления связанного приложения, это обновление выполняется достаточно быстро. Затем из обновленного приложения также средствами EDT делается выгрузка конфигурации в cf, эта выгрузка занимает секунды 2-3 (на конфигурации размером 250 мб, без поставки конечно же). Далее, создание таблицы изменений двух коммитов (здесь Git как пуля) и подготовка настроек слияния (конфигуратор хорош) занимает также считанные секунды.

Сейчас вам, читающим эти строки, это всё кажется очевидным, для меня же реализация этой схемы была равносильна "переходу от лучины к атомной энергетике". Изначально всё было примитивно - переключиться на коммит 1, выгрузить проект в XML, затем из XML собрать cf, переключиться на коммит 2, повторить, получить второй cf, сравнить два cf, распарсить отчет о сравнении, подготовить список объектов для захвата по данным отчета. Весь этот конвейер отрабатывал 10 минут(!), даже если в коммите была изменена всего лишь одна строка кода... да уж, можно было успеть кофейку намешать и даже выпить, новости почитать и т.д. На этом этапе я еще не догадывался про настройки слияния (AutoMergeSetting.xml), что это программное отражение всех тех действий, которые можно выполнить интерактивно из окна Сравнения/объединения в конфигураторе, да и в целом узнал новые для себя свойства этого окна. Кроме этого, не догадывался, что при слиянии конфигурации по умолчанию используется поиск только по именам объектов и интерактивно повлиять на это поведение нельзя, только программно. Тест подсветил мне эту проблему и подтолкнул на исследование этого вопроса.

 

Сценарий использования

 

Теперь, зная как устроен механизм отправки/получения, понимая концепт рабочего процесса, без повторения инструкции по работе в EDT покажу сценарий разработки в EDT конфигурации, версионирующейся в хранилище.

(Сначала прочитать полностью, без выполнения шагов).

Контекст: Файловая разработческая база с конфигурацией Demo, подключенной к хранилищу.

 

1. Настройка
 

1.1 Разворачивание конфигурации в EDT
 

  1. Установить EDT.
  2. Установить и настроить все компоненты, ссылки в разделе "Компоненты" выше.
    1. включить плагины gitsync:
      1. increment
      2. tool1CD
      3. edtExport (обязателен)
      4. disable-support
      5. sortProject
  3. Настроить перспективу Git.
    Работа с коммитами происходит в этом рабочем месте, фокус только на Git и хранилище. Располагаем в удобном месте окно Консоль, Состояние и История. Убедиться, что в окне История появились две стрелки.
  4. Отключить автоматическое обновление рабочей области при внешних изменениях: Общие-Рабочая область-Автоматически обновлять рабочую область при внешних изменениях... Проект самостоятельно обновляется после сделанных в нем изменениях, это поведение предусмотрено в плагине EDT.
  5. В EDT импортировать конфигурацию Demo из разработческой базы. Будет создан проект EDT.
  6. В настройках проекта включить автосортировку всех объектов. Это по желанию.
  7. Перед созданием git репозитория ознакомиться со статьей https://its.1c.ru/db/edtdoc#content:10054:hdoc. Обратить внимание на Git LFS.
  8. Проект EDT перевести в git репозиторий.
  9. В каталог проекта Demo, находящийся в созданном репозитории, закинуть файлы AUTHORS, VERSION, autumn-properties.json. В корень репозитория, до кучи добавить gitignore, как минимум с исключением файлов *.json.

    Структура репозитория:


     

    Структура каталога проекта (файл ConfigDumpInfo.xml создается автоматически гитсинком):



     
    1. AUTHORS должен быть заполнен тем же составом разработчиков, которые представлены в списке пользователей хранилища.
    2. В файле VERSION должна быть заполнена версия.
      Считаю достаточным залить себе в репозиторий только последний коммит из хранилища. Не стоит тянуть себе всю историю, это может быть долго, очень долго. У меня на работе настроен gitsync, годами уже работает, выгружает коммиты хранилища в git в формате XML, поэтому нет проблем с обращением к истории разработки, git blame всегда под рукой. Можете также настроить, пусть в фоне выгружает хранилище в git для анализа истории, а себе в репозиторий EDT подтяните только последнюю версию хранилища.
    3. Заполните файл настроек autumn-properties.json.
      Настоятельно рекомендую заполнить ключ БазаПодключеннаяКХранилищу. Здесь нужно указать настройки разработческой базы, подключенной к хранилищу. Это позволит вернуться к работе с хранилищем из конфигуратора без необходимости переподключения к хранилищу, что может занять достаточно длительное время.
       
  10. Закоммитить инициализацию репозитория проекта Demo. Автоматически будет создана новая ветка master, которой будет принадлежать созданный коммит.
  11. Можно стартовать получение коммитов из хранилища. Ничего страшного, если конфигурация проекта уже соответствует последней версии хранилища. Как минимум обновится версия в файле VERSION.
  12. Если получение коммитов из хранилища произошло успешно, значит всё настроено корректно. Можно пушить в хранилище.

 

1.2 Подключение расширений
 

Контекст: Должна быть развернута конфигурация проекта, к которой будет относиться расширение.

  1. Переключиться на master.
  2. Импортировать расширения из разработческой базы.
  3. Перенести проект расширения в репозиторий.
    Не бороться с предлагаемой структурой репозитория. В отдельном каталоге репозитория должен находиться проект основной конфигурации, в соседнем каталоге - расширение к этой конфигурации. Имена каталогов проектов не стоит править.
  4. В проект расширения добавить файлы AUTHORS, VERSION, autumn-properties.json.
  5. Закоммитить инициализацию проекта расширения.
  6. Запустить операцию получения коммитов из хранилища этого расширения.
  7. Если получение коммитов произошло успешно, значит всё настроено корректно. Можно пушить в хранилище.

 

2. Разработка
 

  1. Актуализировать master, запустив операцию получения коммитов из хранилища.
  2. Создать feature ветку от ветки master с именем равным тикету задачи (ну или как там у вас принято).
  3. Выполнить доработку конфигурации согласно задаче. Проверить. Перед финальным коммитом фича-ветки в ней может быть создано несколько коммитов, это нормально.
  4. Актуализировать master.
  5. Влить master в фича-ветку.
    1. Если появилось окно сравнения-объединения, вручную разрешить возникший неразрешимый конфликт.
  6. Возник коммит слияния, merged branch. У этого коммита два предка - последний коммит мастера и последний коммит фича-ветки. На коммите слияния висит метка HEAD, это важно, метка HEAD подсвечивает коммит, который будет использоваться для получения изменений.
  7. Нажимаем кнопку отправки в хранилище.
  8. Появляется диалоговое окно для ввода сообщения коммита и подтверждения или переопределения коммита предка, второго коммита, который будет использован для получения изменений.
    Как определяется коммит-предок? Просто. Берется ближайший предок. В случае с коммитом слияния, ближайший предок выбирается из ветки master, это всегда будет коммит с меткой master, т.е. последний коммит мастера. Но, можно переопределить автоматически установленный коммит предка на любого другого предка, в этом случае в пул изменений попадут все изменения, которые попадают в диапазон между HEAD и выбранным предком. Нажимаем ОК.
  9. В рамках операции Push, чекается актуальность версии хранилища.
    1. Если версии не совпадают, то будет вежливо предложено актуализироваться, это сообщение невозможно не заметить. В этом случае нужно будет обновить master и повторить слияние мастера в фича-ветку.
  10. Далее автоматически готовится фактура для предъявления в хранилище. Затем выполняется захват объектов и помещение в хранилище.
    1. Если часть объектов уже кем-то захвачена, возникает ошибка, материмся, откладываем коммит, переходим к следующей задаче, вернемся к этому коммиту, когда объекты освободят.

Как видите, процесс максимально прост и быстр.

 

2.1 Замечания
 

  1. Мы можем работать с любым объектом как конфигурации, так и расширения, мы легко и незаметно для себя можем перепрыгивать с объекта расширения на объект конфигурации. Не стоит забывать, что и основная конфигурации и все расширения хранятся в отдельных проектах, у них есть свои хранилища и мы не выбираем какой конкретно проект нужно синхронизировать, синхронизируются все проекты последовательно в порядке сначала основная конфигурация, затем расширения. Соответственно, если вы добавите много расширений, синхронизация в вашем случае будет выполняться долго.
  2. Следует из первого замечания. Рассмотрим случай, когда у нас есть конфигурация проекта и несколько проектов расширений к нему. Есть такой лайфхак - закоммитить одним коммитом доработки, выполненные сразу как в основной конфигурации, так и во всех связанных расширениях. Стоит ли этим пользоваться? Наверное нет, если это не какой-то служебный коммит, где нам нужно добавить одни и те же изменения во все проекты - конфигурации и расширениях к ней.
    Поэтому совет - когда в индекс попали доработки как конфигурации, так и расширения, то коммитить нужно последовательно и здесь для удобства желательно включить иерархический просмотр индекса.
  3. Изменения, отправляемые в хранилище, рассчитываются между HEAD и parent. Если необходимо переключить HEAD на другой коммит, то это нужно делать через создание и извлечение ветки на том коммите, на который нужно переключить HEAD. В общем, корректный HEAD будет только когда он указывает на ветку.

 

Cопровождение и развитие

 

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

Основная часть, связанная непосредственно с получением и отправкой изменений вынесена в onescript, благодаря этому снизился порог для участия в доработке этих инструментов.

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

Вообще, мне понравилась идея вынесения функционала на onescript, который затем подключаем к интерфейсу EDT в виде кнопочек через плагины. Эта идея и заложена в консольном приложении jeweltools. Это набор инструментов для работы с драгоценными камнями утилит, подключаемых к EDT и расширяющих возможности EDT. Сейчас там две утилиты - export и v8storage. Есть идея добавить утилиту по запуску сонарсканера, когда перед коммитом в хранилище можно будет чекать выполненные доработки в сонаре. Да много чего можно подключить к EDT таким образом, многочисленные библиотеки oscript позволят реализовать много безумных идей.

 

Где тесты?

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

Запуск тестов. Из каталога репозитория jeweltools вызвать oneunit execute.

В тесте Тест_ИзмененияКонфигурацииПроектаВХранилище выполняется три сценария:

  1. В пустую конфигурацию добавляются новые объекты каждого(!) типа. Затем все эти новые объекты улетают в хранилище. После помещения объектов в хранилище, выполняется сравнение конфигурации хранилища с эталонной конфигурацией.
  2. Изменены все добавленные объекты путем добавления "1" к имени объектов. На этом же шаге выполняется и проверка сопоставления объектов по guid - мы же изменили имя объекта, т.е. поломали сопоставление по имени. Для проверки сопоставления по гуидам были отдельно добавлены подсистемы с хитрыми именами, которые корректно могут быть сопоставлены только по guid (если сопоставлять по именам, то будет пересорт). Также после помещения объектов в хранилище, выполняется сравнение конфигурации хранилища с эталонной конфигурацией.
  3. Удалены все добавленные объекты. Аналогично.

В тесте Тест_ИзмененияРасширенияВХранилище выполняются те же три сценария, но только для пары-тройки объектов - добавленных в расширение и заимствованных из основной конфигурации.

Это лютые тесты, без слез не взглянешь, но рабочие.

Данные тесты были созданы не столько по причине обложить тестом сложный участок, а скорее по причине продемонстрировать стабильность и корректность отправки в хранилище самых разных, порой экзотических объектов на максимально широкой выборке и в различных состояниях - добавление/изменение/удаление.

При выполнении Тест_ИзмененияКонфигурацииПроектаВХранилище был найден баг платформы, который уже подтвердили и выдали номер ошибки 60031903 (https://regevent.1c.ru/sbo/tp/59167951-4eb9-11f1-81ac-0050569f2415/info/). Есть такой сложносоставной объект ВнешниеИсточникиДанных. За одну итерацию слияния переносится только часть этого объекта и для переноса остальной части необходимо повторить слияние. Мне пришлось добавить костыль, чтобы обойти этот баг. Устранят ли этот баг? Одному Богу известно. Вероятно, что никогда.

Что касается остальных участков, не менее сложных, то здесь я допустил отсутствие тестов (надеюсь временно), т.к. это не критичные участки, в том смысле, что, если что-то пойдет не так, мы это сразу увидим, в отличии от операции помещения изменений в хранилище. А именно, если залагает плагин EDT, то мы просто не сможем синхронизироваться с хранилищем, тут всё просто - либо управление передается на jeweltools, либо плагин нам говорит - братан извини, ты обновил EDT и мне что-то поплохело. В случае с автосортировкой мы увидим возникшие изменения в индексе по причине выполненной сортировки самой EDT и при этом родная сортировка перестала совпадать с сортировкой, выполненной плагином sortProject.

Что еще?

Пытливый исследователь, изучая мои тексты может заметить, что у меня нигде нет списка типов всех объектов платформы и может возникнуть вопрос - а как ты понимаешь, где какой тип, что вот тут нужно брать "catalog", а там "catalogs"? Я не храню список всех возможных типов, я беру их из файлов метаданных. По этой причине моя реализация остается стабильной при возможных будущих появлениях новых типов. Стало быть не нужно поддерживать такой список с выходом новой платформы, там оно само разберётся, что есть что. Это достигается анализом и сопоставлением файлов mdo и ConfigDumpInfo, который создается гитсинком при включенном плагине increment.

 

Замечания

  1. Проблема всплывающих изменений при сравнении конфигураций.
    Достаточно известная и старая проблема. О чем речь? Если выгрузить конфигурацию из приложения проекта и сравнить ее с конфигурацией хранилища той же версии, то вместо пустого окна сравнения-объединения мы увидим непонятно откуда взявшиеся изменения. Много видел/слышал жалоб по этой проблеме. По ней написано не мало задач в edt issues https://github.com/1C-Company/1c-edt-issues. Разработчикам давно известна эта проблема, они с ней борются, доработки проводятся с двух сторон - со стороны EDT и платформы, так что, если хочется максимально снизить проявление этой проблемы, нужно постоянно обновляться на новые версии EDT и платформы, что очевидно на практике не реализуемо.
    Как я решил для себя эту проблему - я просто сказал себе "да и хрен с ним". Ну действительно, это неразрешимая проблема, с ней ничего нельзя сделать, остается только изменить своё отношение к этому и подумать - а действительно ли это настолько серьезная проблема?

    1. На своей практике я достаточно редко сталкивался с такими аномалиями.
    2. Если возникает аномалия, я сразу вижу, что это аномалия, а не осознанная человеческая доработка, поэтому сразу это пропускаю, не обращаю на неё внимания.
    3. У меня есть только один момент, когда эти аномалии мне помешали. Т.к. автоматический коммит в хранилище дело серьезное, никакой проверки тут нет, то мне видилось логичным добавить автоматическую проверку залитых в хранилище изменений. Так вот, такую проверку я и не могу сделать по причине этих аномалий, они будут мешать сравнению с эталоном.
  2. EDTшная сортировка выполняется не по всем объектам. Например, сортировка подчиненных подсистем самой EDT не выполняется, но такая сортировка выполняется плагином sortProject и это поведение не конфликтует с EDTшной сортировкой, т.е. расширять состав сортируемых объектов можно, но в части пересекающихся сортируемых объектов правила сортировки должны совпадать. Тут главное не увлекаться и не добавить в сортировку измерения регистров.

  3. В продолжение про плагин сортировки. Реализация механизма сортировки такова, что содержимое файлов метаданных mdo пересобирается, потому что порядок следования XML узлов свойств объектов и формирует порядок в дереве объектов. В формате mdo есть особенность в экранировании спецсимволов. Здесь используется какой-то хитрый xml парсер, среди всех спецсимволов экранируются только три:

    Спецсимвол Экранирование
    " "
    < &lt;
    & &amp;


    К примеру, объект ЗаписьXML экранирует только &  и <, >. Экранирует обе угловые скобки и не экранирует кавычки. Пришлось самостоятельно экранировать  спецсимволы, чтобы подстроиться под хитрый парсер EDT.

  4.  jeweltools имеет недостаток - сейчас запуск приложения должен происходить строго из каталога, в котором находится файл настроек autumn-properties.json. Кроме этого, при запуске jeweltools инициализируются все желуди - нужные и не нужные. Для той идеи, которую я заложил в это приложение, такое поведение, по-моему, является избыточным. Пока еще не разобрался как сделать по красоте. Например, есть Табакерка, которая препятствует инициализации желудя в памяти при старте приложения и тогда затабакеренные желуди можно стартовать по требованию. Но в этом случае, получается нужно все желуди табакерить, а табакерка, как я понял, задумывалась не для массового применения, а для каких-то редких желудей. Есть еще Заготовка, СоветМастера. Механизмы слабо документированы, сходу не понять, нужно время чтобы во всем разобраться и научиться жарить желуди правильно.

  5. Поддержка Linux. Теоретически должно работать, не проверял. Жесткой привязки к Windows нет. Если не взлетит, то наверняка по какой-то мелочи, пишите, поправлю.

 

P.S. По итогу всё равно получился лонгрид, надеюсь, читатель меня простит. Это была моя первая публикация.

 

Выражаю благодарность всем авторам используемых мной утилит и библиотек и тем, кто принял участие в их развитии, поименно всех вас не перечислить. Без ваших ценных разработок я бы пилил синхронизацию с хранилищем ещё бы полгода, а то и год, вероятно даже 5 лет, хотя к тому времени "ишак уже бы сдох" :)

 

Дмитрий Шеховцев, г.Владивосток, 2026г.

Вступайте в нашу телеграмм-группу Инфостарт

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Нейросети EDT Программист 1С:Предприятие 8 Бесплатно (free)

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

16.07.2026    1813    1Concept    0    

4

Нейросети EDT Программист 1С:Предприятие 8 Россия Абонемент ($m)

LLM-агенты уже неплохо рассуждают о коде 1С — но рассуждают вслепую. Модель не видит вашу конфигурацию: ей либо копируют модули в чат руками, либо выгружают конфигурацию в файлы и индексируют — и индекс устаревает в момент первой правки. А главное — агент не может ничего сделать: прочитал, посоветовал, а вносить правку снова человеку. Мы решали эту задачу для своей линейки 1C Intelligence Suite — это её вторая часть, о которой мы рассказываем публично.

1 стартмани

08.07.2026    4419    galich    13    

9

EDT Программист 1С:Предприятие 8 Россия Бесплатно (free)

EDT стала средой, которую можно дорабатывать под себя обычному 1С-нику без особых знаний Java. На примере плагина EDT Extension Tweaks показываю, как с помощью Codex удалось закрыть боль с контекстом расширений, внешних обработок, СКД и конструктора запросов.

25.06.2026    3826    shchukin_vv    26    

29

EDT Программист 1С 8.3 1С 8.5 1С:Управление торговлей 11 Абонемент ($m)

Плагин для 1C:EDT, который контролирует изменения структуры базы данных и экспортных процедур между версиями конфигурации. Сохраняет контрольные точки релизов, сравнивает текущую разработку с выпущенной версией, автоматически находит опасные изменения (удаление таблиц и колонок, изменение типов, сужение размеров) и показывает их в удобной панели прямо в EDT с цветовой индикацией по уровню риска. Помогает избежать потери данных при обновлении.

3 стартмани

08.06.2026    2042    sqr4    2    

3

EDT Программист 1С 8.3 1С 8.5 1С:Библиотека стандартных подсистем Россия Абонемент ($m)

Нативный плагин для 1C:EDT, который анализирует цикломатическую и когнитивную сложность BSL-кода. Показывает метрики прямо в редакторе над каждым методом, помогает находить сложные участки кода и принимать решения о рефакторинге

1 стартмани

13.05.2026    954    5    sqr4    13    

4

EDT Программист 1С 8.3 1С 8.5 1С:Библиотека стандартных подсистем Россия Абонемент ($m)

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

3 стартмани

12.05.2026    1181    3    sqr4    0    

7
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. пользователь 10.07.26 20:15
Одна из лучших статей про edt + хранилище.
Спасибо
2. baracuda 2 11.07.26 17:05 Сейчас в теме
Как будто бы смысла в этом немного, раз уже начали работать с EDT, почему бы полностью не отказаться от хранилища.
amiralnar; +1 Ответить
3. DmitryShehovtsev 25 12.07.26 06:07 Сейчас в теме
(2) В коротком разделе "Для кого это всё" я дал ответ на ваш вопрос. Я видел подобные вопросы, когда читал похожие статьи про EDT и хранилище. В этом комментарии попробую дополнить этот раздел. Я работаю в корпоративной команде, где 20+ разработчиков и я один из них кто работает в EDT. Надеюсь с этой поделкой я смогу обратить в свою веру пару-тройку коллег по команде. Не стоит сбрасывать со счетов хранилище, его время еще не прошло, наверное не ошибусь, если назову цифру - 70% сидят в хранилище, 25% в EDT, 5% - на экзотике конфигуратор+Git. Даже если вы разработчик-одиночка фрилансер, разрабатывающий в EDT, может поступить заказ, где вам предложат разработать один из компонентов общего механизма в сотрудничестве с другими разработчиками, как самого заказчика так и сторонних. И вам предъявили требование - вам выдается доступ к удаленному хранилищу, вы должны коммитить в это хранилище по каждой задаче, а не один супер-коммит в конце рабочего дня сразу на все выполненные задачи. Почему хранилище? Цифры выше, вы скорее найдете матёрого эксперта, который работает в конфигураторе, чем в EDT. Как вы будете работать по такой схеме, не имея возможности простой синхронизации EDT и хранилища? Конечно, каждый коммит можно вручную выгружать в cf и затем также вручную сливать в хранилище, я так и работал в первое время (именно выгрузка в хранилище, а загрузкой из хранилища занимался gitsync), но потом понял, что так жить нельзя, нужно автоматизировать этот процесс.
4. NeTan-root 14.07.26 09:30 Сейчас в теме
Здравствуйте, Дмитрий! Спасибо за инструмент и статью, идея отличная.

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

Моя ситуация. Хранилище у нас серверное, адрес вида tcp://server:порт/ИмяХранилища. Рабочая база уже постоянно подключена к хранилищу под отдельным логином. Наш нынешний гитконвертер умеет инкрементально получать изменения именно через отдельно подключённую базу (обновление конфигурации из хранилища → инкрементальная выгрузка в файлы → сборка в формат EDT → коммит в master). Хочу понять, вписывается ли ваш инструмент в такую схему (серверное хранилище + заранее подключённая база для инкрементального получения изменений или помещения изменений).

Что развернул для теста: v8storagesync 0.1.2, jeweltools 0.1.0, gitsync 3.7.3 с плагинами increment/tool1CD/disable-support/edtExport/sortProject, EDT 2026.1, платформа 8.3.21.

Посмотрел исходники и вижу следующее — верно ли?

1. Получение (pull). Подкоманда ПодкомандаПолучитьИзмененияИзХранилища делегирует всё в gitsync sync, передавая GITSYNC_STORAGE_PATH = ФС.ПолныйПуть(Настройки["Путь"]). Для tcp-адреса ФС.ПолныйПуть превращает его в (несуществующий) локальный путь. Плюс gitsync с tool1CD читает 1cv8ddb.1CD напрямую. Получается, pull рассчитан только на файловое хранилище, а инкрементальность даёт increment/ConfigDumpInfo, а не подключённая база. Вопрос: есть ли режим инкрементального получения через уже подключённую базу (как в классическом конвертере — /ConfigurationRepositoryUpdateCfg + инкрементальная выгрузка), или это всегда чтение файла через tool1CD?

2. Помещение (push). БазаПодключеннаяКХранилищу позволяет использовать постоянную подключённую базу как контекст (ВременныйКонтекст = Ложь, привязка временной базы пропускается) — это удобно. Но при этом:

ПроверитьАктуальностьВерсииХранилища() через ЧтениеФайловойБазы.ТекущаяВерсияХранилища() читает <Путь>\1cv8ddb.1CD напрямую (cTool_1CD), и это самая первая операция push;
МенеджерКонфигуратора при захвате/коммите/слиянии передаёт платформе ФС.ПолныйПуть(Настройки["Путь"]) как путь к хранилищу, а в ПодключитьсяКХранилищу есть проверка существования 1cv8ddb.1CD. То есть даже с заранее подключённой базой push всё равно упирается в прямой файловый доступ к каталогу хранилища. Вопрос: можно ли выполнить инкрементальный push исключительно через подключённую базу по tcp, без файлового доступа к 1cv8ddb.1CD?
3. Итог по tcp. Правильно ли, что сейчас обязателен прямой файловый доступ к каталогу хранилища (где лежит 1cv8ddb.1CD), а серверное хранилище по tcp:// не поддерживается — из-за (а) прогона пути через ФС.ПолныйПуть и (б) чтения версии/данных из 1cv8ddb.1CD через cTool_1CD? Или я что-то упускаю, и tcp всё же можно настроить?

И если ограничение подтвердится — планируется ли поддержка серверного хранилища через подключённую базу? Навскидку для этого нужно: не прогонять tcp-путь через ФС.ПолныйПуть; брать текущую версию хранилища платформенным /ConfigurationRepositoryReport (в либе v8storage уже есть ПолучитьТаблицуВерсийХранилища) вместо чтения 1cv8ddb.1CD; а контекстом использовать подключённую базу.

Заранее спасибо за пояснения!
6. DmitryShehovtsev 25 15.07.26 12:49 Сейчас в теме
(4) Добрый день! Спасибо за ценные замечания.
Я разработку вел только в контексте файловых баз, т.к. сам я по рабочим задачам использую файловые базы, поэтому все остальные способы подключения к хранилищу не были протестированы.
1. Здесь присутствует недоработка. Конечно же tool1CD должен использоваться только для файловых баз.
2. Те же замечания присутствуют для отправки в хранилище. Есть замечания при использовании временной базы.
3. Да, пока только файловый вариант стабильный.
Уже работаю над доработками, в ближайшее время (день-два) выпущу обновление.
NeTan-root; +1 Ответить
7. DmitryShehovtsev 25 16.07.26 19:07 Сейчас в теме
(4) Выпустил обновление jeweltools. Попутно поправил плагин edt для случая использования расширений. Не совсем понимаю вашу задумку использовать данную синхронизацию с гитконвертером. Проверьте ваш сценарий по сделанным доработкам, если остаются вопросы с гитконвертером, распишите подробнее вашу схему. Навскидку, предлагаю использовать либо гитсинк для получения коммитов из хранилища в ЕДТ, либо использовать только команду v8storage push для отправки коммитов из ЕДТ в хранилище, т.к. коммиты из хранилища у вас подтягиваются в ЕДТ гитконвертером.
8. NeTan-root 17.07.26 07:58 Сейчас в теме
(7)
Спасибо, супер, что так оперативно! Обязательно протестирую обновление (в т.ч. правку по расширениям) и отпишусь по результатам.

Поясню про гитконвертер — я привёл его лишь как пример текущей схемы, и я готов от него отказаться, если ваше решение закроет мой кейс. Ключевым был не сам конвертер, а способ работы с хранилищем.

Суть вот в чём. У меня тяжёлая конфигурация (уровня ERP) и серверное хранилище (tcp://…). При таком объёме критично, чтобы синхронизация была инкрементальной в обе стороны и не выкачивала/не разворачивала полные снимки:

Получение. Нужно именно «обновление из хранилища» на уже подключённой базе (/ConfigurationRepositoryUpdateCfg — платформа накатывает только дельту между версиями), а затем инкрементальная выгрузка в файлы. Многие инструменты «из коробки» для каждой версии выкачивали и разворачивали полный снимок конфигурации — на ERP это неприемлемо долго. Мой доработанный конвертер как раз получает изменения инкрементально через подключённую базу — поэтому я за него и держался.

Отправка. Аналогично — захватывать и помещать в хранилище только изменённые объекты (как у вас и описано в статье), без выгрузки/заливки полного состава конфигурации.

То есть мой вопрос был не «конвертер против вашего плагина», а: может ли ваш инструмент получать и помещать изменения инкрементально через подключённую базу по tcp, без полных снимков. Если да — с радостью откажусь от конвертера и полностью перейду на ваше решение.

Ваши варианты понял (gitsync на получение / v8storage push на отправку) — в идеале хочу обе стороны инкрементально и, по возможности, одним инструментом. Проверю свежую сборку на своём серверном хранилище и вернусь с результатами.

Ещё раз спасибо за оперативность и за инструмент!
9. NeTan-root 17.07.26 10:20 Сейчас в теме
(7)
Я немного потестировал и параллельно поизучал код, чтобы лучше понять механику.
Возможно, часть этого уже учтена — поправьте, если так.

1. Отдельная постоянная база, подключённая к хранилищу.
На мой взгляд, обмен с хранилищем стоит вести через отдельную базу, постоянно подключённую к хранилищу, которую задаёшь (или создаёшь) один раз в настройках.

Через неё:
получение — обновление конфигурации из хранилища;
отправка — помещение изменений в хранилище.

А база, подключённая к EDT (где ведётся разработка), к хранилищу не подключается и остаётся только для разработки.

Причины:
- базу, подключённую к хранилищу, нельзя менять без захвата объектов, то есть разрабатывать в ней невозможно — значит, база разработки и база-проводник должны быть разными;

- захват объектов логично делать только в момент отправки готовых изменений и сразу снимать после коммита; держать объекты захваченными во время разработки нельзя — это блокирует коллег и рушит саму идею работы в EDT;

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

2. Инкрементальность получения и -v N.
Заметил, что версии накатываются через /ConfigurationRepositoryUpdateCfg -v N по каждой версии. Насколько вижу, на серверном хранилище (tcp) указание конкретной версии -v N тянет полный снимок этой версии, а не дельту — на ERP это выходит долго. У себя я решал это так: одна постоянная база-зеркало, подключённая к хранилищу один раз, и далее накат до последней версии без указания -v (обновление до HEAD) — платформа переносит только дельту, а промежуточные версии схлопываются в один коммит.

Если такой режим (постоянная база-проводник + накат до HEAD одной дельтой) впишется в вашу архитектуру — для серверных хранилищ на тяжёлых конфигурациях это было бы очень кстати. Понимаю, что инструмент изначально делался под файловые базы, поэтому это скорее пожелание и направление, а не претензия. Спасибо за труд и открытость к обратной связи!
10. DmitryShehovtsev 25 18.07.26 15:35 Сейчас в теме
(9) Ответы в соответствии с вашими пунктами:
1. Всё правильно пишите, эта идея и реализована в данном инструменте )
База подключенная к хранилищу это чисто для удобства разработчику, больше никакого функционала она не несет. Для какого сценария это сделано? - Разработчик хочет сохранить возможность вернуться в родной конфигуратор, если в EDT у него что-то не пойдет. Такое бывает - что-то делаешь в EDT, потом вылазит какая-то херня, тратишь время, чтобы в этом разобраться, а можно просто рукой махнуть и продолжить разработку в конфигураторе. Т.е. это сценарий, когда разработчик оставляет дверь открытой, не сжигает мосты )
"...то есть разрабатывать в ней невозможно — значит, база разработки и база-проводник должны быть разными" - мне кажется разработчику нужно определиться - либо EDT, либо конфигуратор. База-проводник усложняет схему.
"захват объектов логично делать только в момент отправки готовых изменений и сразу снимать после коммита; держать объекты захваченными во время разработки нельзя — это блокирует коллег и рушит саму идею работы в EDT" - именно так всё и работает, в статье подробно про это написано, там же описываю и выполняемые блокировки при отправке в хранилище, коллеги же не сидели сложа руки, пока мы разрабатывали в EDT.
"и только постоянная, единожды подключённая база сохраняет инкрементальность: если базу пересоздавать/переподключать под каждую операцию, каждый раз идёт полная загрузка снимка." - по поводу инкрементальности:
2. Будет ли использоваться инкрементальный режим, зависит от характера сделанных изменений. Для процесса получения из хранилища (сторона gitsync) используется платформенный механизм, который рассчитывает дельту по файлу ConfigDumpInfo.xml. Если были изменены имена метаданных или было удаление метаданных (например, переименовали справочник Номенклатура в Товары или удалили справочник Номенклатура), то будет выполнен Full dump, полная выгрузка в файлы и дальнейшая конвертация в формат EDT, это нужно учитывать, но это редкий сценарий. Для случая отправки в хранилище используется git для определения разности изменений и только эта разность отравляется в хранилище, где объекты уже сопоставляются по гуидам. При загрузке из хранилища (получение в EDT) используется инкрементальный режим (в gitsync должен быть включен плагин increment, иначе каждая версия будет выгружаться полностью), это можно увидеть по логам, там будет что-то типа "ИСПОЛЬЗУЕТСЯ ИНКРЕМЕНТАЛЬНАЯ ВЫГРУЗКА" (капсом). Итого, в этом я уверен и на практике это постоянно вижу - при получении зачастую используется инкрементальный режим (за редким исключением, о котором написал выше) и при отправке используется инкрементальный режим, но это происходит только на стороне EDT при инкрементальном обновлении связанного приложения. Когда управление передается команде v8storage push там уже нет такого понятия как инкрементальный режим, т.к. там уже git этим занимается. Но, на стороне EDT при обновлении приложения используется тот же платформенный механизм и механика там та же - если было переименование или удаление, связанное приложение будет обновляться полностью, через выгрузку всех файлов, что можно будет наблюдать по статусной строке в окне Состояние.
"Заметил, что версии накатываются через /ConfigurationRepositoryUpdateCfg -v N по каждой версии. Насколько вижу, на серверном хранилище (tcp) указание конкретной версии -v N тянет полный снимок этой версии, а не дельту" - нет, используется команда DumpConfigToFiles с ключом -update, смотрите плагин "%LOCALAPPDATA%\gitsync\plugins\gitsync-plugins\src\Классы\increment.os". Кстати, советую обновить все плагины из каталога Классы на свежие версии из репозитория gitsync-plugins.
Для отправки сообщения требуется регистрация/авторизация