Files
docs/public/template-sync-strategy/llms-full.txt

1010 lines
35 KiB
Plaintext
Raw Normal View History

---
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`.