Files
docs/public/template-sync-strategy/llms-full.txt
S.Gromov 1a14df9366 feat: добавить документацию Template Sync Strategy
- добавлены каноны и VitePress-сайт стратегии обновления шаблонов

- подключена карточка документации на главной странице

- добавлены сборочные скрипты, Caddy-маршрут и Docker-сборка

- добавлена git-иконка для карточки и сгенерированы публичные артефакты
2026-05-13 23:23:31 +03:00

1010 lines
35 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
url: /template-sync-strategy/overview.md
description: >-
Управляемое обновление проектов от шаблона через чистую ветку template,
временные sync-ветки и PR/MR.
---
# Template Sync Strategy
Template Sync Strategy описывает процесс, при котором приложение создаётся от шаблона и дальше регулярно получает обновления шаблона без ручного копирования файлов.
Основной маршрут:
```text
templates/master -> template -> sync/* -> master
```
Где:
* `templates/master` — основная ветка внешнего репозитория шаблона.
* `template` — чистый слепок шаблона внутри репозитория приложения.
* `sync/*` — временная ветка, где шаблон накладывается на приложение.
* `master` — основная ветка приложения.
## Задача
Шаблон хорошо решает старт проекта: приносит CI/CD, Dockerfile, зависимости, линтер, сборку, структуру и базовую документацию. Но после старта приложения расходятся: где-то обновили CI, где-то забыли, где-то сделали локальную кастомизацию.
Стратегия нужна, чтобы шаблон оставался общей технической базой не только в первый день проекта, но и на всём жизненном цикле приложения.
## Главный принцип
Ветка `template` должна оставаться чистым слепком оригинального шаблона.
В неё нельзя коммитить изменения приложения и нельзя решать конфликты. Все конфликтные решения выполняются только во временных ветках `sync/*`.
## Состав документации
* [Зачем это нужно](./concepts/why.md) — какие проблемы появляются без update-flow.
* [Модель веток](./concepts/model.md) — роли `templates/master`, `template`, `sync/*` и `master`.
* [Правила процесса](./concepts/rules.md) — ограничения, которые удерживают схему чистой.
* [Новый проект от шаблона](./setup/clean-repository.md) — старт приложения с правильной историей.
* [Миграция существующего master](./setup/existing-master-migration.md) — одноразовое связывание несвязанных историй.
* [Обычное обновление шаблона](./workflows/update-template.md) — регулярный рабочий процесс.
* [Решение конфликтов](./workflows/resolve-conflicts.md) — где и как совместить шаблон с приложением.
* [Review и merge](./workflows/review-and-merge.md) — как доставлять sync-ветку в `master`.
* [Памятка](./reference/cheatsheet.md) — короткий набор команд.
* [Troubleshooting](./reference/troubleshooting.md) — типовые ошибки и диагностика.
* [Глоссарий](./reference/glossary.md) — основные термины.
---
---
url: /template-sync-strategy/concepts/why.md
description: >-
Почему шаблону нужен процесс обновления, а не только быстрый старт нового
проекта.
---
# Зачем это нужно
Шаблон закрывает повторяющуюся техническую базу проекта: CI/CD, Dockerfile, зависимости, lint, build, структуру каталогов и базовую документацию.
Это снимает рутину на старте. Команде не нужно каждый раз заново собирать одинаковый технический каркас.
## Проблема после старта
Создать проект легко. Поддерживать 10-20 проектов сложнее.
Сначала проекты похожи. Потом они начинают расходиться:
* В одном проекте обновили CI, в другом забыли.
* В одном проекте Dockerfile остался из шаблона, в другом его локально поправили.
* В одном проекте зависимости уже свежие, в другом остались старые версии.
* В одном проекте изменения шаблона перенесли руками, в другом потеряли.
Без процесса обновления шаблон перестаёт быть общей основой. Он остаётся только способом быстро создать первый коммит.
## Что ломается без стратегии
Когда шаблон нельзя нормально обновлять:
* проекты начинают жить своей жизнью;
* граница между шаблоном и приложением теряется;
* обновления превращаются в ручное копирование;
* конфликты решаются прямо в рабочих ветках;
* становится непонятно, какой проект на какой версии шаблона;
* Git-история перестаёт быть источником правды.
Это особенно больно, когда приложений много. Для одного проекта ручной перенос ещё можно пережить. Для набора проектов нужен единый маршрут обновления.
## Цель стратегии
Стратегия не пытается убрать конфликты полностью. Она делает так, чтобы конфликты возникали в предсказуемом месте, проходили review и не ломали чистую ветку шаблона.
Главная формулировка:
> Шаблон должен обновляться так же контролируемо, как обычная фича: через ветку, проверку и PR/MR.
---
---
url: /template-sync-strategy/concepts/model.md
description: Роли веток и remote в стратегии обновления проекта от шаблона.
---
# Модель веток
Целевая схема:
```text
templates/master -> template -> sync/* -> master
```
Это логическая модель ответственности. Она не требует физически разделять файлы шаблона и приложения по папкам.
## templates/master
`templates/master` — это `master` из репозитория шаблона.
В репозитории приложения он доступен через remote `templates`:
```bash
git remote add templates <template-repo-url>
git fetch templates
```
Этот remote считается источником обновлений шаблона.
## template
`template` — чистый слепок шаблона внутри репозитория приложения.
Его задача — показать, какая версия шаблонной базы сейчас доступна приложению.
В `template` нельзя коммитить руками изменения приложения. Эта ветка обновляется только из `templates/master`.
## master
`master` — основная ветка приложения.
Она содержит:
* базу шаблона;
* продуктовый код;
* локальные настройки приложения;
* историю применения обновлений шаблона.
`master` не используется как место ручного решения конфликтов при обновлении шаблона.
## sync/\*
`sync/*` — временная ветка для обновления приложения от шаблона.
Она создаётся от актуального `origin/master`, после чего в неё вливается `origin/template`.
Пример:
```bash
git fetch origin
git switch -c sync/update-template-v2 origin/master
git merge origin/template
```
Если появляются конфликты, они решаются именно в этой ветке.
## Почему нужен отдельный sync-слой
Нельзя безопасно использовать `template` как source branch для прямого PR/MR в `master`: если возникнет конфликт, решение может попасть в `template`.
После этого `template` перестанет быть чистым слепком шаблона. Git начнёт видеть в ней не только шаблон, но и локальные решения конкретного приложения.
`sync/*` можно пачкать conflict resolve-коммитами, проверками и правками совместимости. Эта ветка временная и удаляется после merge.
---
---
url: /template-sync-strategy/concepts/rules.md
description: >-
Набор правил, который удерживает template чистой, а обновления шаблона
контролируемыми.
---
# Правила процесса
Небольшой набор правил удерживает схему чистой.
## Делаем
* `template` обновляем только из `templates/master`.
* `sync/*` создаём от `origin/master`.
* `origin/template` вливаем в `sync/*`, а не напрямую в `master`.
* Конфликты решаем только в `sync/*`.
* `sync/* -> master` вливаем через PR/MR.
* Для sync-PR/MR отключаем squash.
## Не делаем
* Не правим `template` руками.
* Не коммитим изменения приложения в `template`.
* Не мержим `template -> master` напрямую.
* Не решаем конфликты в `master`.
* Не включаем squash для `sync/* -> master`.
## Почему squash нельзя
Squash может уничтожить нормальную связь истории `master` с историей `template`.
Git использует историю, чтобы понимать, какие изменения шаблона уже были доставлены в приложение. Если результат обновления шаблона превратить в один squash-коммит, связь с исходными коммитами шаблона станет хуже или исчезнет.
Для sync-PR/MR допустимы:
```text
fast-forward merge = хорошо
merge commit = допустимо
squash merge = нельзя
```
## Почему template нельзя пачкать
`template` — эталонный слепок оригинального шаблона.
Если в неё попадает локальное решение конфликта или изменение приложения, она перестаёт отвечать на вопрос: “какая версия шаблона сейчас подключена к приложению?”.
После этого ломается главная граница ответственности: шаблон отдельно, приложение отдельно, конфликтная зона отдельно.
---
---
url: /template-sync-strategy/setup/clean-repository.md
description: Старт нового приложения от шаблонного репозитория с правильной историей веток.
---
# Новый проект от шаблона
Этот сценарий подходит, когда репозиторий приложения ещё пустой или его можно безопасно пересоздать от шаблона.
Целевая модель:
```text
templates/master -> template -> sync/* -> master
```
## Условия
Есть два репозитория:
```text
template repo = репозиторий шаблона
app repo = репозиторий приложения
```
В обоих репозиториях основная ветка называется `master`.
## Подготовить шаблон
В репозитории шаблона:
```bash
cd /path/to/template-repo
git switch master
```
Если это пустой репозиторий, добавьте первый файл и запушьте `master`:
```bash
printf "# Template Repository\n\nBase template version: v1\n" > README.md
git add README.md
git commit -m "docs: добавить базовый шаблон"
git push -u origin master
```
## Подключить шаблон в приложении
В репозитории приложения:
```bash
cd /path/to/app-repo
git remote add templates <template-repo-url>
git fetch templates
```
Создайте ветку `template` от шаблона:
```bash
git switch -c template templates/master
git push -u origin template
```
Создайте ветку приложения `master` от `template`:
```bash
git switch -c master template
```
Добавьте слой приложения:
```bash
mkdir -p app
printf "Application code v1\n" > app/app.txt
git add app/app.txt
git commit -m "feat: добавить слой приложения"
git push -u origin master
```
После этого история выглядит так:
```text
template: T1
master: T1---A1
```
Где `T1` — коммит шаблона, а `A1` — коммит приложения.
## Настроить pull и push для template
Можно сделать так, чтобы на ветке `template`:
```text
git pull тянул из templates/master
git push пушил в origin/template
```
Команды:
```bash
git config branch.template.remote templates
git config branch.template.merge refs/heads/master
git config branch.template.pushRemote origin
```
Дополнительно можно запретить случайный push в репозиторий шаблона:
```bash
git remote set-url --push templates DISABLED
```
## Дальше
После первичной настройки постоянные ветки такие:
```text
template = чистый шаблон
master = приложение
```
Обновления шаблона выполняются через временные ветки `sync/*` по инструкции [Обычное обновление шаблона](../workflows/update-template.md).
---
---
url: /template-sync-strategy/setup/existing-master-migration.md
description: >-
Как одноразово связать master приложения с историей шаблона, если проект был
создан отдельно.
---
# Миграция существующего master
Этот сценарий нужен, если в репозитории приложения уже есть `master`, но он был создан не от шаблона.
## Проблема
Если `master` приложения и `template` имеют разные корневые коммиты, Git видит две несвязанные истории.
Плохое состояние:
```text
template: T1---T2---T3
master: A1---A2
```
При попытке выполнить обычный merge Git может ответить:
```text
fatal: отказ слияния несвязанных историй изменений
```
Это означает, что у веток нет общего предка.
## Цель миграции
Нужно один раз связать истории, чтобы дальше обновления шаблона шли обычным merge-процессом.
После миграции история будет выглядеть примерно так:
```text
template: T1---T2---T3
\
master: A1---A2-----M
```
Где `M` — одноразовый merge-коммит, который связал историю приложения с историей шаблона.
## Подключить репозиторий шаблона
В репозитории приложения:
```bash
cd /path/to/app-repo
git remote add templates <template-repo-url>
git fetch templates
git fetch origin
```
Если remote `templates` уже существует:
```bash
git fetch templates
git fetch origin
```
## Создать или обновить template
Если ветки `template` ещё нет:
```bash
git switch -c template templates/master
git push -u origin template
```
Если ветка `template` уже есть:
```bash
git switch template
git merge --ff-only templates/master
git push origin template
```
Опционально настройте удобное поведение `pull` и `push`:
```bash
git config branch.template.remote templates
git config branch.template.merge refs/heads/master
git config branch.template.pushRemote origin
git remote set-url --push templates DISABLED
```
## Связать master с template
Создайте временную ветку от текущего приложения:
```bash
git fetch origin
git switch -c sync/bootstrap-template origin/master
```
Слейте шаблон с разрешением несвязанных историй:
```bash
git merge --allow-unrelated-histories origin/template
```
Если есть конфликты, решите их в ветке `sync/bootstrap-template`:
```bash
git add .
git commit
```
Если конфликтов не было, Git сам создаст merge-коммит.
Запушьте ветку:
```bash
git push -u origin sync/bootstrap-template
```
Дальше через UI или локально смержите:
```text
sync/bootstrap-template -> master
```
## Что проверить перед merge
Посмотрите граф истории:
```bash
git --no-pager log --oneline --graph --decorate --all --max-count=50
```
Убедитесь, что `sync/bootstrap-template` содержит и историю приложения, и историю шаблона.
Посмотрите итоговый diff:
```bash
git --no-pager diff origin/master...sync/bootstrap-template
```
## Когда миграцию делать не стоит
Не стоит связывать истории, если приложение только что создано и его можно безопасно пересоздать от шаблона.
Для нового проекта лучше сделать чистый старт по инструкции [Новый проект от шаблона](./clean-repository.md).
---
---
url: /template-sync-strategy/workflows/update-template.md
description: >-
Повторяемый процесс доставки изменений шаблона в приложение после первичной
настройки.
---
# Обычное обновление шаблона
Эта инструкция подходит после любого стартового сценария:
* [Новый проект от шаблона](../setup/clean-repository.md).
* [Миграция существующего master](../setup/existing-master-migration.md).
Целевой маршрут:
```text
templates/master -> template -> sync/* -> master
```
## 1. Обновить слепок шаблона
В репозитории приложения:
```bash
cd /path/to/app-repo
git switch template
git pull --ff-only
git push
```
Этот вариант работает, если для ветки `template` настроено:
```text
pull из templates/master
push в origin/template
```
Явная форма без зависимости от tracking-настроек:
```bash
git fetch templates
git switch template
git merge --ff-only templates/master
git push origin template
```
Если `--ff-only` падает, значит `template` перестал быть чистым слепком шаблона. Остановитесь и разберите причину до продолжения.
Проверьте, что `origin/template` обновился до шаблона:
```bash
git fetch origin
git fetch templates
git --no-pager log --oneline -1 origin/template
git --no-pager log --oneline -1 templates/master
```
Оба коммита должны совпадать.
## 2. Создать ветку обновления приложения
После обновления `template` создайте временную ветку от текущего приложения:
```bash
git fetch origin
git switch -c sync/update-template-v2 origin/master
git merge origin/template
```
Имя ветки можно менять под версию или дату:
```text
sync/update-template-v2
sync/update-template-2026-05-09
sync/update-template-1.8.0
```
Проверьте, что временная ветка реально отличается от `origin/master` изменениями шаблона:
```bash
git --no-pager diff --stat origin/master...HEAD
```
Если diff пустой, значит обновлённый `origin/template` не был влит в `sync/*` ветку или в шаблоне нет новых изменений.
## 3. Решить конфликты
Если есть конфликты, решайте их именно в `sync/*`.
После решения конфликтов:
```bash
git add .
git commit
```
Если конфликтов не было, Git сам создаст merge-коммит или выполнит fast-forward, в зависимости от истории.
## 4. Запушить sync-ветку
```bash
git push -u origin sync/update-template-v2
```
Дальше откройте PR/MR:
```text
source: sync/update-template-v2
target: master
```
Правила merge описаны в [Review и merge](./review-and-merge.md).
---
---
url: /template-sync-strategy/workflows/resolve-conflicts.md
description: Почему конфликты при обновлении шаблона должны решаться только в sync-ветках.
---
# Решение конфликтов
Конфликт при обновлении шаблона — нормальная ситуация. Важно не то, что конфликт возник, а где он возник.
Правильное место для конфликтов — временная ветка `sync/*`.
## Пример
Шаблон поменял строку в `README.md`:
```text
Base template version: template-conflict-v10
```
Приложение поменяло ту же строку иначе:
```text
Base template version: application-conflict-v10
```
При merge `origin/template` в `sync/update-template-v10` появится конфликт:
```text
<<<<<<< HEAD
Base template version: application-conflict-v10
=======
Base template version: template-conflict-v10
>>>>>>> origin/template
```
Это правильное место конфликта: `master` ещё не изменён, `template` остаётся чистой, а итоговое решение можно проверить в PR/MR.
## Как решать
1. Оставайтесь в ветке `sync/*`.
2. Разберите конфликт по смыслу: что должно остаться в приложении после обновления шаблона.
3. Удалите conflict markers.
4. Проверьте проект локально.
5. Закоммитьте результат.
```bash
git status
git add .
git commit
```
## Что нельзя делать
Нельзя переносить conflict resolve в `template`.
`template` должна совпадать с шаблоном. Если решение конфликта попадёт туда, она перестанет быть эталоном и дальнейшие обновления станут менее предсказуемыми.
Нельзя решать конфликт прямо в `master`, потому что основная ветка приложения должна получать только проверенный результат через PR/MR.
## Что проверить после resolve
Посмотрите статус:
```bash
git status
```
Посмотрите diff относительно текущего приложения:
```bash
git --no-pager diff origin/master...HEAD
```
Посмотрите граф:
```bash
git --no-pager log --oneline --graph --decorate --all --max-count=50
```
---
---
url: /template-sync-strategy/workflows/review-and-merge.md
description: Как проверять и вливать sync-ветку с обновлением шаблона в master приложения.
---
# Review и merge
После подготовки `sync/*` ветки обновление шаблона должно попасть в `master` через PR/MR.
## Создать PR/MR
Параметры:
```text
source: sync/update-template-vX
target: master
```
Цель review — увидеть:
* какие изменения пришли из шаблона;
* какие конфликтные решения были сделаны в `sync/*`;
* не попали ли в обновление лишние изменения приложения;
* проходят ли проверки проекта.
## Настройки merge
Для sync-PR/MR важно:
```text
squash = off
fast-forward merge = хорошо
merge commit = допустимо
squash merge = нельзя
```
Squash нельзя использовать, потому что он может уничтожить связь истории `master` с историей `template`. Особенно это критично после миграционного `sync/bootstrap-template`.
## Проверки перед merge
Проверьте граф истории:
```bash
git --no-pager log --oneline --graph --decorate --all --max-count=50
```
Проверьте итоговый diff:
```bash
git --no-pager diff origin/master...sync/update-template-vX
```
Проверьте проект обычными командами конкретного приложения, например:
```bash
npm run lint
npm run build
```
## После merge
После успешного merge в `master` можно удалить временную ветку:
```bash
git branch -d sync/update-template-vX
git push origin --delete sync/update-template-vX
```
Проверьте, что `master` теперь содержит обновление шаблона:
```bash
git fetch origin
git --no-pager log origin/template..origin/master --oneline
git --no-pager diff origin/template...origin/master
```
---
---
url: /template-sync-strategy/reference/cheatsheet.md
description: Короткий набор команд для регулярного обновления приложения от шаблона.
---
# Памятка
Рабочая схема:
```text
templates/master -> template -> sync/* -> master
```
## Обновить template
В репозитории приложения:
```bash
git switch template
git pull --ff-only
git push
```
Это подтягивает свежий шаблон из `templates/master` и пушит его в `origin/template`.
## Создать ветку обновления
```bash
git fetch origin
git switch -c sync/update-template-vX origin/master
git merge origin/template
```
Если есть конфликты, решить их в этой же ветке:
```bash
git add .
git commit
```
## Запушить sync-ветку
```bash
git push -u origin sync/update-template-vX
```
## Влить через UI
Создать PR/MR:
```text
source: sync/update-template-vX
target: master
```
Важно:
```text
squash = off
```
## Проверка
```bash
git --no-pager log --oneline --graph --decorate --all --max-count=30
```
## Суть процесса
1. Обновить `template` из `templates/master`.
2. Создать `sync/*` от `origin/master`.
3. Влить `origin/template` в `sync/*`.
4. Решить конфликты, если есть.
5. Запушить `sync/*`.
6. Через UI влить `sync/* -> master`.
---
---
url: /template-sync-strategy/reference/troubleshooting.md
description: Типовые ошибки при обновлении проекта от шаблона и способы диагностики.
---
# Troubleshooting
## fatal: отказ слияния несвязанных историй изменений
Ошибка:
```text
fatal: отказ слияния несвязанных историй изменений
```
Причина: `master` приложения не был создан от `template`, поэтому у веток нет общего предка.
Решение: выполнить одноразовую миграцию через `sync/bootstrap-template` по инструкции [Миграция существующего master](../setup/existing-master-migration.md).
Коротко:
```bash
git switch -c sync/bootstrap-template origin/master
git merge --allow-unrelated-histories origin/template
git push -u origin sync/bootstrap-template
```
## --ff-only падает на template
Ошибка возникает при команде:
```bash
git merge --ff-only templates/master
```
Причина: в `template` появились коммиты, которых нет в шаблоне. Значит ветка перестала быть чистым слепком.
Что проверить:
```bash
git fetch templates
git --no-pager log --oneline --graph --decorate templates/master..template
```
Решение зависит от причины. Не продолжайте обновление, пока не станет понятно, какие локальные коммиты попали в `template`.
## Пустой diff в sync-ветке
Симптом:
```bash
git --no-pager diff --stat origin/master...HEAD
```
не показывает изменений.
Возможные причины:
* в шаблоне нет новых изменений;
* `origin/template` не был обновлён;
* `origin/template` не был влит в `sync/*`;
* sync-ветка создана не от актуального `origin/master`.
Что проверить:
```bash
git fetch origin
git fetch templates
git --no-pager log --oneline -1 origin/template
git --no-pager log --oneline -1 templates/master
git --no-pager log --oneline --graph --decorate --all --max-count=50
```
## Случайно включили squash
Если sync-PR/MR уже влит squash-merge, история шаблона могла не сохраниться как нормальная merge-связь.
Что сделать:
* зафиксировать факт в описании проекта;
* проверить, видит ли Git последующие обновления шаблона без повторного применения старых изменений;
* при следующем обновлении внимательно смотреть diff и конфликты;
* для будущих sync-PR/MR отключить squash.
Если ситуация стала неуправляемой, может потребоваться отдельная техническая миграция истории.
## cannot run less
Ошибка:
```text
cannot run less
```
Причина: Git пытается открыть pager `less`, которого нет в системе.
Решение: использовать `git --no-pager`:
```bash
git --no-pager log --oneline --graph --decorate --all --max-count=50
git --no-pager diff template...master
```
---
---
url: /template-sync-strategy/reference/glossary.md
description: 'Термины, которые используются в Template Sync Strategy.'
---
# Глоссарий
## Template repo
Репозиторий шаблона. В нём живёт общая техническая база: CI/CD, Dockerfile, зависимости, линтер, сборка, структура и документация.
## App repo
Репозиторий приложения. В нём живёт продуктовый код и локальные настройки конкретного приложения.
## templates
Git remote внутри репозитория приложения, который указывает на репозиторий шаблона.
Пример:
```bash
git remote add templates <template-repo-url>
```
## templates/master
Ветка `master` из репозитория шаблона, доступная в приложении через remote `templates`.
## template
Ветка внутри репозитория приложения, которая должна быть чистым слепком `templates/master`.
## master
Основная ветка приложения. Содержит шаблонную базу плюс продуктовый слой.
## sync/\*
Временные ветки для обновления приложения от шаблона. Создаются от `origin/master`, получают merge из `origin/template`, проходят review и затем вливаются в `master`.
## Fast-forward
Обновление ветки без merge-коммита, когда текущая ветка может быть просто передвинута вперёд по истории.
## Merge commit
Коммит слияния, который сохраняет связь двух историй. Допустим для `sync/* -> master`.
## Squash
Способ merge, при котором все изменения source branch превращаются в один новый коммит. Для sync-PR/MR запрещён, потому что может разрушить полезную связь истории `master` с историей `template`.