chore: добавить сборку frontend-агента
All checks were successful
CI/CD Pipeline / build (push) Successful in 35s
CI/CD Pipeline / docker (push) Successful in 1m7s
CI/CD Pipeline / deploy (push) Successful in 7s

- добавлен агент frontend-architect с манифестом и reference-картой

- добавлен скрипт сборки архива агента в public/agents

- добавлена сборка агентов в CI и Docker-сборку

- исключены generated-директории public/agents и public/template-sync-strategy

- удалены сгенерированные файлы Template Sync Strategy из git
This commit is contained in:
2026-05-17 18:39:14 +03:00
parent 93f4b468c4
commit a53c5fc1b1
83 changed files with 340 additions and 2590 deletions

View File

@@ -8,6 +8,8 @@ docs/*/.vitepress/dist
docs/*/content
public/slm-design
public/figma-adaptive-standards
public/template-sync-strategy
public/agents
*.log
.DS_Store
.env*

View File

@@ -32,6 +32,9 @@ jobs:
- name: Генерация корневых артефактов
run: npm run site:generate
- name: Сборка агентов
run: npm run agents:build
- name: Сборка лендинга
run: npm run build

2
.gitignore vendored
View File

@@ -19,6 +19,8 @@ public/llms.txt
public/slm-design/
public/nextjs-style-guide/
public/figma-adaptive-standards/
public/template-sync-strategy/
public/agents/
# Editor directories and files
.vscode/*

View File

@@ -6,7 +6,7 @@ COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run docs:build:slm-design && npm run docs:build:nextjs-style-guide && npm run docs:build:figma-adaptive-standards && npm run docs:build:template-sync-strategy && npm run build
RUN npm run docs:build:slm-design && npm run docs:build:nextjs-style-guide && npm run docs:build:figma-adaptive-standards && npm run docs:build:template-sync-strategy && npm run agents:build && npm run build
FROM caddy:2-alpine

View File

@@ -0,0 +1,189 @@
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
type ReferenceConfig = {
references: Array<{
source: string;
target: string;
}>;
};
type ZipEntry = {
name: string;
content: Buffer;
};
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const agentDir = path.resolve(scriptDir, '..');
const rootDir = path.resolve(agentDir, '../..');
const sourceDir = path.join(agentDir, 'source');
const tempDir = path.join(agentDir, '.tmp');
const packageName = 'frontend-architect';
const packageDir = path.join(tempDir, packageName);
const publicAgentsDir = path.join(rootDir, 'public', 'agents');
const zipPath = path.join(publicAgentsDir, `${packageName}.zip`);
function readJson<T>(filePath: string): T {
return JSON.parse(fs.readFileSync(filePath, 'utf8')) as T;
}
function copyFile(sourcePath: string, targetPath: string) {
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
fs.copyFileSync(sourcePath, targetPath);
}
function collectFiles(dir: string, baseDir = dir): ZipEntry[] {
return fs
.readdirSync(dir, { withFileTypes: true })
.flatMap((entry) => {
const entryPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
return collectFiles(entryPath, baseDir);
}
const relativePath = path.relative(baseDir, entryPath).split(path.sep).join('/');
return [
{
name: `${packageName}/${relativePath}`,
content: fs.readFileSync(entryPath),
},
];
})
.sort((a, b) => a.name.localeCompare(b.name));
}
function createCrc32Table() {
return Array.from({ length: 256 }, (_, index) => {
let value = index;
for (let bit = 0; bit < 8; bit += 1) {
value = value & 1 ? 0xedb88320 ^ (value >>> 1) : value >>> 1;
}
return value >>> 0;
});
}
const crc32Table = createCrc32Table();
function crc32(buffer: Buffer) {
let crc = 0xffffffff;
for (const byte of buffer) {
crc = crc32Table[(crc ^ byte) & 0xff] ^ (crc >>> 8);
}
return (crc ^ 0xffffffff) >>> 0;
}
function writeUInt16(value: number) {
const buffer = Buffer.alloc(2);
buffer.writeUInt16LE(value, 0);
return buffer;
}
function writeUInt32(value: number) {
const buffer = Buffer.alloc(4);
buffer.writeUInt32LE(value >>> 0, 0);
return buffer;
}
function createZip(entries: ZipEntry[]) {
const localParts: Buffer[] = [];
const centralParts: Buffer[] = [];
const dosTime = 0;
const dosDate = ((2026 - 1980) << 9) | (1 << 5) | 1;
let offset = 0;
for (const entry of entries) {
const fileName = Buffer.from(entry.name, 'utf8');
const checksum = crc32(entry.content);
const size = entry.content.length;
const localHeader = Buffer.concat([
writeUInt32(0x04034b50),
writeUInt16(20),
writeUInt16(0),
writeUInt16(0),
writeUInt16(dosTime),
writeUInt16(dosDate),
writeUInt32(checksum),
writeUInt32(size),
writeUInt32(size),
writeUInt16(fileName.length),
writeUInt16(0),
fileName,
]);
localParts.push(localHeader, entry.content);
const centralHeader = Buffer.concat([
writeUInt32(0x02014b50),
writeUInt16(20),
writeUInt16(20),
writeUInt16(0),
writeUInt16(0),
writeUInt16(dosTime),
writeUInt16(dosDate),
writeUInt32(checksum),
writeUInt32(size),
writeUInt32(size),
writeUInt16(fileName.length),
writeUInt16(0),
writeUInt16(0),
writeUInt16(0),
writeUInt16(0),
writeUInt32(0),
writeUInt32(offset),
fileName,
]);
centralParts.push(centralHeader);
offset += localHeader.length + size;
}
const centralDirectory = Buffer.concat(centralParts);
const endOfCentralDirectory = Buffer.concat([
writeUInt32(0x06054b50),
writeUInt16(0),
writeUInt16(0),
writeUInt16(entries.length),
writeUInt16(entries.length),
writeUInt32(centralDirectory.length),
writeUInt32(offset),
writeUInt16(0),
]);
return Buffer.concat([...localParts, centralDirectory, endOfCentralDirectory]);
}
function buildAgent() {
const referencesConfig = readJson<ReferenceConfig>(path.join(sourceDir, 'references.json'));
fs.rmSync(tempDir, { recursive: true, force: true });
fs.mkdirSync(packageDir, { recursive: true });
copyFile(path.join(sourceDir, 'AGENT.md'), path.join(packageDir, 'AGENT.md'));
copyFile(path.join(sourceDir, 'manifest.json'), path.join(packageDir, 'manifest.json'));
for (const reference of referencesConfig.references) {
const sourcePath = path.join(rootDir, reference.source);
if (!fs.existsSync(sourcePath)) {
throw new Error(`Reference not found: ${reference.source}`);
}
copyFile(sourcePath, path.join(packageDir, reference.target));
}
fs.mkdirSync(publicAgentsDir, { recursive: true });
fs.writeFileSync(zipPath, createZip(collectFiles(packageDir)));
fs.rmSync(tempDir, { recursive: true, force: true });
console.log(`Built ${path.relative(rootDir, zipPath)}`);
}
buildAgent();

View File

@@ -0,0 +1,88 @@
# Frontend Architect
## Роль
Ты frontend-архитектор проекта. К тебе обращаются, когда нужно понять, как правильно спроектировать frontend-часть задачи: где создать код, какие модули затронуть, как разделить ответственность, как связать части приложения и не сломать архитектурные границы.
В этом проекте архитектурным стандартом является SLM Design. Используй его как рабочую модель для всех решений: слой, модуль, сегмент, публичный API, направление зависимостей, business factory и композиция.
## Граница ответственности
- По умолчанию не пиши production-код.
- Не реализуй фичи как frontend-разработчик без явного запроса пользователя.
- Проектируй реализацию задачи: какие слои, модули, сегменты, public API и factory нужны.
- Точно указывай, где создавать или изменять файлы: слой, модуль, сегмент, назначение файла.
- Объясняй, почему код должен жить именно там, а не в другом месте.
- Проводь архитектурное ревью существующего или предлагаемого кода.
- Переходи к правкам кода только если пользователь явно попросил внести изменения.
## Архитектурная основа
Единственная архитектура проекта — SLM Design. Все frontend-решения принимай только в терминах SLM: слой, модуль, сегмент, публичный API, направление зависимостей, business factory.
Не вводи альтернативные архитектурные модели и не объясняй решения через них.
## Рабочий процесс
1. Пойми пользовательскую задачу как frontend-изменение: экран, фича, домен, UI-блок, сервис, состояние, данные или инфраструктура.
2. Найди существующую структуру проекта, если решение зависит от текущего кода.
3. Определи слой SLM, где должна жить основная ответственность.
4. Определи модуль или модули, которые нужно создать или изменить.
5. Определи сегменты и конкретные файлы внутри модулей.
6. Определи публичные API, допустимые импорты и runtime-зависимости.
7. Если решение спорное, открой relevant reference и принимай решение по нему.
8. Сформулируй итог: как реализовать задачу по SLM, куда что положить, какие границы не нарушать.
9. Если пользователь попросил код, сначала зафиксируй архитектурное решение, потом выполняй минимальные правки.
## Инварианты SLM
- Импорты между модулями идут только через публичный API.
- Deep imports во внутренние сегменты чужого модуля запрещены.
- Зависимости идут по направлению SLM-слоёв.
- Runtime-связи между business-доменами идут через factory.
- `import type` не считается runtime-зависимостью.
- Доменные типы не выносятся в `shared`.
- `shared` не знает о продукте и доменах.
- `ui` не содержит бизнес-логику, сценарную логику и обращения к API.
## Архитектурные развилки
При спорных решениях не пересказывай правила из памяти. Открой нужный reference и прими решение по нему.
- Слой и направление зависимостей → `references/slm-layers.md`.
- Модуль, компонент, публичный API, factory → `references/slm-modules.md`.
- Размещение файлов внутри модуля → `references/slm-segments.md`.
- Monorepo и `packages/*``references/slm-monorepo.md`.
- Business factory → `references/slm-react-factory.md`.
- Композиция business factories → `references/slm-react-factory-composition.md`.
- Композиция через Provider → `references/slm-react-composition-provider.md`.
## Что проектировать
- Новый экран: определить `screens/{name}`, локальные `parts/`, нужные business/widget/ui зависимости.
- Новый UI-блок: решить, это локальный `parts/`, `widgets`, `business/{domain}/parts` или `ui`.
- Новая фича: определить доменную принадлежность, business-модуль, factory API и точку композиции.
- Новый business-домен: определить factory, types, hooks/services/mappers/ui и public API.
- Новый сервис: определить, это `infra` или локальная часть модуля.
- Общая утилита: проверить, действительно ли это `shared`, а не локальный `lib/` модуля.
- Monorepo-вынос: проверить, допустим ли `packages/ui`, `packages/infra` или `packages/shared`.
## Формат ответа
Если пользователь просит архитектурное решение, отвечай коротко:
```text
Решение: ...
Почему: ...
Куда: ...
Что создать/изменить: ...
Зависимости: ...
Ограничения: ...
Reference: ...
```
Если пользователь просит ревью, сначала перечисли нарушения и риски, затем предложи SLM-совместимое исправление.
## Поведение при конфликте
Если запрос пользователя требует нарушить SLM, не делай это молча. Коротко объясни конфликт и предложи SLM-совместимый вариант. Если правил недостаточно для решения, задай один уточняющий вопрос.

View File

@@ -0,0 +1,17 @@
{
"name": "frontend-architect",
"title": "Frontend Architect",
"version": "0.1.0",
"description": "Frontend-архитектор для работы по SLM Design.",
"entry": "AGENT.md",
"references": [
"references/slm-overview.md",
"references/slm-layers.md",
"references/slm-modules.md",
"references/slm-segments.md",
"references/slm-monorepo.md",
"references/slm-react-factory.md",
"references/slm-react-factory-composition.md",
"references/slm-react-composition-provider.md"
]
}

View File

@@ -0,0 +1,36 @@
{
"references": [
{
"source": "canons/slm-design/architecture/index.md",
"target": "references/slm-overview.md"
},
{
"source": "canons/slm-design/architecture/layers.md",
"target": "references/slm-layers.md"
},
{
"source": "canons/slm-design/architecture/modules.md",
"target": "references/slm-modules.md"
},
{
"source": "canons/slm-design/architecture/segments.md",
"target": "references/slm-segments.md"
},
{
"source": "canons/slm-design/architecture/monorepo.md",
"target": "references/slm-monorepo.md"
},
{
"source": "canons/slm-design/examples/react/factory.md",
"target": "references/slm-react-factory.md"
},
{
"source": "canons/slm-design/examples/react/factory-composition.md",
"target": "references/slm-react-factory-composition.md"
},
{
"source": "canons/slm-design/examples/react/composition-provider.md",
"target": "references/slm-react-composition-provider.md"
}
]
}

View File

@@ -15,6 +15,8 @@
"docs:prepare:template-sync-strategy": "tsx scripts/docs/prepare.ts template-sync-strategy",
"docs:build:template-sync-strategy": "npm run docs:prepare:template-sync-strategy && vitepress build docs/template-sync-strategy",
"site:generate": "tsx scripts/site/generate-artifacts.ts",
"agent:build:frontend-architect": "tsx agents/frontend-architect/scripts/build.ts",
"agents:build": "npm run agent:build:frontend-architect",
"lint": "eslint .",
"preview": "vite preview"
},

View File

@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html lang="en-US" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>404 | Template Sync Strategy</title>
<meta name="description" content="Not Found">
<meta name="generator" content="VitePress v1.6.4">
<link rel="preload stylesheet" href="/template-sync-strategy/assets/style.CSIvdBoa.css" as="style">
<link rel="preload stylesheet" href="/template-sync-strategy/vp-icons.css" as="style">
<script type="module" src="/template-sync-strategy/assets/app.0Bzyh7PD.js"></script>
<link rel="preload" href="/template-sync-strategy/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
<script id="sync-docs-theme">(()=>{if(localStorage.getItem("vitepress-theme-appearance"))return;const e=localStorage.getItem("all-docs-theme");e&&(localStorage.setItem("vitepress-theme-appearance",e==="system"?"auto":e),localStorage.removeItem("all-docs-theme"))})();</script>
<script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
<script id="check-mac-os">document.documentElement.classList.toggle("mac",/Mac|iPhone|iPod|iPad/i.test(navigator.platform));</script>
</head>
<body>
<div id="app"></div>
<script>window.__VP_HASH_MAP__=JSON.parse("{\"concepts_model.md\":\"C805A9As\",\"concepts_rules.md\":\"QraT4IhZ\",\"concepts_why.md\":\"akfw90Fj\",\"index.md\":\"C5Q_ZnE3\",\"overview.md\":\"DOeHHuHO\",\"reference_cheatsheet.md\":\"0TzKSaSb\",\"reference_glossary.md\":\"DLD-b2Ke\",\"reference_troubleshooting.md\":\"BrYSpYuW\",\"setup_clean-repository.md\":\"CPqmBfph\",\"setup_existing-master-migration.md\":\"BQ5VImS9\",\"workflows_resolve-conflicts.md\":\"CujNWdsi\",\"workflows_review-and-merge.md\":\"D5KhlAbu\",\"workflows_update-template.md\":\"C8s1FFCq\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"Template Sync Strategy\",\"description\":\"Управляемое обновление проектов от шаблона\",\"base\":\"/template-sync-strategy/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":true,\"themeConfig\":{\"sidebar\":[{\"text\":\"Введение\",\"items\":[{\"text\":\"Обзор\",\"link\":\"/overview\"},{\"text\":\"Зачем это нужно\",\"link\":\"/concepts/why\"},{\"text\":\"Модель веток\",\"link\":\"/concepts/model\"},{\"text\":\"Правила процесса\",\"link\":\"/concepts/rules\"}]},{\"text\":\"Настройка\",\"items\":[{\"text\":\"Новый проект от шаблона\",\"link\":\"/setup/clean-repository\"},{\"text\":\"Миграция существующего master\",\"link\":\"/setup/existing-master-migration\"}]},{\"text\":\"Рабочие процессы\",\"items\":[{\"text\":\"Обычное обновление шаблона\",\"link\":\"/workflows/update-template\"},{\"text\":\"Решение конфликтов\",\"link\":\"/workflows/resolve-conflicts\"},{\"text\":\"Review и merge\",\"link\":\"/workflows/review-and-merge\"}]},{\"text\":\"Справочник\",\"items\":[{\"text\":\"Памятка\",\"link\":\"/reference/cheatsheet\"},{\"text\":\"Troubleshooting\",\"link\":\"/reference/troubleshooting\"},{\"text\":\"Глоссарий\",\"link\":\"/reference/glossary\"}]}],\"socialLinks\":[]},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":true}");</script>
</body>
</html>

View File

@@ -1 +0,0 @@
import{R as p}from"./chunks/theme.CloMnL7i.js";import{R as s,a1 as i,a2 as u,a3 as c,a4 as l,a5 as f,a6 as d,a7 as m,a8 as h,a9 as g,aa as A,d as v,u as R,v as w,s as y,ab as C,ac as P,ad as b,a0 as E}from"./chunks/framework.B1nRs-GM.js";function r(e){if(e.extends){const a=r(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const n=r(p),S=v({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=R();return w(()=>{y(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&C(),P(),b(),n.setup&&n.setup(),()=>E(n.Layout)}});async function T(){globalThis.__VITEPRESS__=!0;const e=_(),a=D();a.provide(u,e);const t=c(e.route);return a.provide(l,t),a.component("Content",f),a.component("ClientOnly",d),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),n.enhanceApp&&await n.enhanceApp({app:a,router:e,siteData:m}),{app:a,router:e,data:t}}function D(){return A(S)}function _(){let e=s;return h(a=>{let t=g(a),o=null;return t&&(e&&(t=t.replace(/\.js$/,".lean.js")),o=import(t)),s&&(e=!1),o},n.NotFound)}s&&T().then(({app:e,router:a,data:t})=>{a.go().then(()=>{i(a.route,t.site),e.mount("#app")})});export{T as createApp};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +0,0 @@
import{_ as a,o as s,c as t,ae as i}from"./chunks/framework.B1nRs-GM.js";const k=JSON.parse('{"title":"Модель веток","description":"Роли веток и remote в стратегии обновления проекта от шаблона.","frontmatter":{"title":"Модель веток","description":"Роли веток и remote в стратегии обновления проекта от шаблона."},"headers":[],"relativePath":"concepts/model.md","filePath":"concepts/model.md"}'),p={name:"concepts/model.md"};function l(n,e,d,o,h,r){return s(),t("div",null,[...e[0]||(e[0]=[i(`<div style="display:none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /template-sync-strategy/concepts/model.md for this page in Markdown format</div><h1 id="модель-веток" tabindex="-1">Модель веток <a class="header-anchor" href="#модель-веток" aria-label="Permalink to &quot;Модель веток&quot;"></a></h1><p>Целевая схема:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>templates/master -&gt; template -&gt; sync/* -&gt; master</span></span></code></pre></div><p>Это логическая модель ответственности. Она не требует физически разделять файлы шаблона и приложения по папкам.</p><h2 id="templates-master" tabindex="-1">templates/master <a class="header-anchor" href="#templates-master" aria-label="Permalink to &quot;templates/master&quot;"></a></h2><p><code>templates/master</code> — это <code>master</code> из репозитория шаблона.</p><p>В репозитории приложения он доступен через remote <code>templates</code>:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> remote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">template-repo-ur</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">l</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span></span></code></pre></div><p>Этот remote считается источником обновлений шаблона.</p><h2 id="template" tabindex="-1">template <a class="header-anchor" href="#template" aria-label="Permalink to &quot;template&quot;"></a></h2><p><code>template</code> — чистый слепок шаблона внутри репозитория приложения.</p><p>Его задача — показать, какая версия шаблонной базы сейчас доступна приложению.</p><p>В <code>template</code> нельзя коммитить руками изменения приложения. Эта ветка обновляется только из <code>templates/master</code>.</p><h2 id="master" tabindex="-1">master <a class="header-anchor" href="#master" aria-label="Permalink to &quot;master&quot;"></a></h2><p><code>master</code> — основная ветка приложения.</p><p>Она содержит:</p><ul><li>базу шаблона;</li><li>продуктовый код;</li><li>локальные настройки приложения;</li><li>историю применения обновлений шаблона.</li></ul><p><code>master</code> не используется как место ручного решения конфликтов при обновлении шаблона.</p><h2 id="sync" tabindex="-1">sync/* <a class="header-anchor" href="#sync" aria-label="Permalink to &quot;sync/*&quot;"></a></h2><p><code>sync/*</code> — временная ветка для обновления приложения от шаблона.</p><p>Она создаётся от актуального <code>origin/master</code>, после чего в неё вливается <code>origin/template</code>.</p><p>Пример:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sync/update-template-v2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/master</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> merge</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/template</span></span></code></pre></div><p>Если появляются конфликты, они решаются именно в этой ветке.</p><h2 id="почему-нужен-отдельныи-sync-слои" tabindex="-1">Почему нужен отдельный sync-слой <a class="header-anchor" href="#почему-нужен-отдельныи-sync-слои" aria-label="Permalink to &quot;Почему нужен отдельный sync-слой&quot;"></a></h2><p>Нельзя безопасно использовать <code>template</code> как source branch для прямого PR/MR в <code>master</code>: если возникнет конфликт, решение может попасть в <code>template</code>.</p><p>После этого <code>template</code> перестанет быть чистым слепком шаблона. Git начнёт видеть в ней не только шаблон, но и локальные решения конкретного приложения.</p><p><code>sync/*</code> можно пачкать conflict resolve-коммитами, проверками и правками совместимости. Эта ветка временная и удаляется после merge.</p>`,29)])])}const m=a(p,[["render",l]]);export{k as __pageData,m as default};

View File

@@ -1 +0,0 @@
import{_ as a,o as s,c as t,ae as i}from"./chunks/framework.B1nRs-GM.js";const k=JSON.parse('{"title":"Модель веток","description":"Роли веток и remote в стратегии обновления проекта от шаблона.","frontmatter":{"title":"Модель веток","description":"Роли веток и remote в стратегии обновления проекта от шаблона."},"headers":[],"relativePath":"concepts/model.md","filePath":"concepts/model.md"}'),p={name:"concepts/model.md"};function l(n,e,d,o,h,r){return s(),t("div",null,[...e[0]||(e[0]=[i("",29)])])}const m=a(p,[["render",l]]);export{k as __pageData,m as default};

View File

@@ -1,3 +0,0 @@
import{_ as a,o as t,c as s,ae as o}from"./chunks/framework.B1nRs-GM.js";const h=JSON.parse('{"title":"Правила процесса","description":"Набор правил, который удерживает template чистой, а обновления шаблона контролируемыми.","frontmatter":{"title":"Правила процесса","description":"Набор правил, который удерживает template чистой, а обновления шаблона контролируемыми."},"headers":[],"relativePath":"concepts/rules.md","filePath":"concepts/rules.md"}'),l={name:"concepts/rules.md"};function c(i,e,d,n,r,p){return t(),s("div",null,[...e[0]||(e[0]=[o(`<div style="display:none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /template-sync-strategy/concepts/rules.md for this page in Markdown format</div><h1 id="правила-процесса" tabindex="-1">Правила процесса <a class="header-anchor" href="#правила-процесса" aria-label="Permalink to &quot;Правила процесса&quot;"></a></h1><p>Небольшой набор правил удерживает схему чистой.</p><h2 id="делаем" tabindex="-1">Делаем <a class="header-anchor" href="#делаем" aria-label="Permalink to &quot;Делаем&quot;"></a></h2><ul><li><code>template</code> обновляем только из <code>templates/master</code>.</li><li><code>sync/*</code> создаём от <code>origin/master</code>.</li><li><code>origin/template</code> вливаем в <code>sync/*</code>, а не напрямую в <code>master</code>.</li><li>Конфликты решаем только в <code>sync/*</code>.</li><li><code>sync/* -&gt; master</code> вливаем через PR/MR.</li><li>Для sync-PR/MR отключаем squash.</li></ul><h2 id="не-делаем" tabindex="-1">Не делаем <a class="header-anchor" href="#не-делаем" aria-label="Permalink to &quot;Не делаем&quot;"></a></h2><ul><li>Не правим <code>template</code> руками.</li><li>Не коммитим изменения приложения в <code>template</code>.</li><li>Не мержим <code>template -&gt; master</code> напрямую.</li><li>Не решаем конфликты в <code>master</code>.</li><li>Не включаем squash для <code>sync/* -&gt; master</code>.</li></ul><h2 id="почему-squash-нельзя" tabindex="-1">Почему squash нельзя <a class="header-anchor" href="#почему-squash-нельзя" aria-label="Permalink to &quot;Почему squash нельзя&quot;"></a></h2><p>Squash может уничтожить нормальную связь истории <code>master</code> с историей <code>template</code>.</p><p>Git использует историю, чтобы понимать, какие изменения шаблона уже были доставлены в приложение. Если результат обновления шаблона превратить в один squash-коммит, связь с исходными коммитами шаблона станет хуже или исчезнет.</p><p>Для sync-PR/MR допустимы:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>fast-forward merge = хорошо</span></span>
<span class="line"><span>merge commit = допустимо</span></span>
<span class="line"><span>squash merge = нельзя</span></span></code></pre></div><h2 id="почему-template-нельзя-пачкать" tabindex="-1">Почему template нельзя пачкать <a class="header-anchor" href="#почему-template-нельзя-пачкать" aria-label="Permalink to &quot;Почему template нельзя пачкать&quot;"></a></h2><p><code>template</code> — эталонный слепок оригинального шаблона.</p><p>Если в неё попадает локальное решение конфликта или изменение приложения, она перестаёт отвечать на вопрос: “какая версия шаблона сейчас подключена к приложению?”.</p><p>После этого ломается главная граница ответственности: шаблон отдельно, приложение отдельно, конфликтная зона отдельно.</p>`,16)])])}const u=a(l,[["render",c]]);export{h as __pageData,u as default};

View File

@@ -1 +0,0 @@
import{_ as a,o as t,c as s,ae as o}from"./chunks/framework.B1nRs-GM.js";const h=JSON.parse('{"title":"Правила процесса","description":"Набор правил, который удерживает template чистой, а обновления шаблона контролируемыми.","frontmatter":{"title":"Правила процесса","description":"Набор правил, который удерживает template чистой, а обновления шаблона контролируемыми."},"headers":[],"relativePath":"concepts/rules.md","filePath":"concepts/rules.md"}'),l={name:"concepts/rules.md"};function c(i,e,d,n,r,p){return t(),s("div",null,[...e[0]||(e[0]=[o("",16)])])}const u=a(l,[["render",c]]);export{h as __pageData,u as default};

View File

@@ -1 +0,0 @@
import{_ as a,o as t,c as i,ae as l}from"./chunks/framework.B1nRs-GM.js";const u=JSON.parse('{"title":"Зачем это нужно","description":"Почему шаблону нужен процесс обновления, а не только быстрый старт нового проекта.","frontmatter":{"title":"Зачем это нужно","description":"Почему шаблону нужен процесс обновления, а не только быстрый старт нового проекта."},"headers":[],"relativePath":"concepts/why.md","filePath":"concepts/why.md"}'),o={name:"concepts/why.md"};function r(n,e,p,c,d,s){return t(),i("div",null,[...e[0]||(e[0]=[l('<div style="display:none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /template-sync-strategy/concepts/why.md for this page in Markdown format</div><h1 id="зачем-это-нужно" tabindex="-1">Зачем это нужно <a class="header-anchor" href="#зачем-это-нужно" aria-label="Permalink to &quot;Зачем это нужно&quot;"></a></h1><p>Шаблон закрывает повторяющуюся техническую базу проекта: CI/CD, Dockerfile, зависимости, lint, build, структуру каталогов и базовую документацию.</p><p>Это снимает рутину на старте. Команде не нужно каждый раз заново собирать одинаковый технический каркас.</p><h2 id="проблема-после-старта" tabindex="-1">Проблема после старта <a class="header-anchor" href="#проблема-после-старта" aria-label="Permalink to &quot;Проблема после старта&quot;"></a></h2><p>Создать проект легко. Поддерживать 10-20 проектов сложнее.</p><p>Сначала проекты похожи. Потом они начинают расходиться:</p><ul><li>В одном проекте обновили CI, в другом забыли.</li><li>В одном проекте Dockerfile остался из шаблона, в другом его локально поправили.</li><li>В одном проекте зависимости уже свежие, в другом остались старые версии.</li><li>В одном проекте изменения шаблона перенесли руками, в другом потеряли.</li></ul><p>Без процесса обновления шаблон перестаёт быть общей основой. Он остаётся только способом быстро создать первый коммит.</p><h2 id="что-ломается-без-стратегии" tabindex="-1">Что ломается без стратегии <a class="header-anchor" href="#что-ломается-без-стратегии" aria-label="Permalink to &quot;Что ломается без стратегии&quot;"></a></h2><p>Когда шаблон нельзя нормально обновлять:</p><ul><li>проекты начинают жить своей жизнью;</li><li>граница между шаблоном и приложением теряется;</li><li>обновления превращаются в ручное копирование;</li><li>конфликты решаются прямо в рабочих ветках;</li><li>становится непонятно, какой проект на какой версии шаблона;</li><li>Git-история перестаёт быть источником правды.</li></ul><p>Это особенно больно, когда приложений много. Для одного проекта ручной перенос ещё можно пережить. Для набора проектов нужен единый маршрут обновления.</p><h2 id="цель-стратегии" tabindex="-1">Цель стратегии <a class="header-anchor" href="#цель-стратегии" aria-label="Permalink to &quot;Цель стратегии&quot;"></a></h2><p>Стратегия не пытается убрать конфликты полностью. Она делает так, чтобы конфликты возникали в предсказуемом месте, проходили review и не ломали чистую ветку шаблона.</p><p>Главная формулировка:</p><blockquote><p>Шаблон должен обновляться так же контролируемо, как обычная фича: через ветку, проверку и PR/MR.</p></blockquote>',17)])])}const _=a(o,[["render",r]]);export{u as __pageData,_ as default};

View File

@@ -1 +0,0 @@
import{_ as a,o as t,c as i,ae as l}from"./chunks/framework.B1nRs-GM.js";const u=JSON.parse('{"title":"Зачем это нужно","description":"Почему шаблону нужен процесс обновления, а не только быстрый старт нового проекта.","frontmatter":{"title":"Зачем это нужно","description":"Почему шаблону нужен процесс обновления, а не только быстрый старт нового проекта."},"headers":[],"relativePath":"concepts/why.md","filePath":"concepts/why.md"}'),o={name:"concepts/why.md"};function r(n,e,p,c,d,s){return t(),i("div",null,[...e[0]||(e[0]=[l("",17)])])}const _=a(o,[["render",r]]);export{u as __pageData,_ as default};

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{_ as t,o as a,c as l,ae as r}from"./chunks/framework.B1nRs-GM.js";const h=JSON.parse('{"title":"Template Sync Strategy","description":"Управляемое обновление проектов от шаблона через чистую ветку template, временные sync-ветки и PR/MR.","frontmatter":{"title":"Template Sync Strategy","description":"Управляемое обновление проектов от шаблона через чистую ветку template, временные sync-ветки и PR/MR.","keywords":["template sync","шаблон проекта","обновление шаблона","git template","sync branch","template branch"]},"headers":[],"relativePath":"index.md","filePath":"index.md"}'),o={name:"index.md"};function i(s,e,c,n,d,p){return a(),l("div",null,[...e[0]||(e[0]=[r("",15)])])}const u=t(o,[["render",i]]);export{h as __pageData,u as default};

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{_ as a,o as t,c as r,ae as l}from"./chunks/framework.B1nRs-GM.js";const h=JSON.parse('{"title":"Template Sync Strategy","description":"Управляемое обновление проектов от шаблона через чистую ветку template, временные sync-ветки и PR/MR.","frontmatter":{"title":"Template Sync Strategy","description":"Управляемое обновление проектов от шаблона через чистую ветку template, временные sync-ветки и PR/MR.","keywords":["template sync","шаблон проекта","обновление шаблона","git template","sync branch","template branch"]},"headers":[],"relativePath":"overview.md","filePath":"overview.md"}'),o={name:"overview.md"};function i(s,e,c,n,d,p){return t(),r("div",null,[...e[0]||(e[0]=[l("",15)])])}const f=a(o,[["render",i]]);export{h as __pageData,f as default};

View File

@@ -1,7 +0,0 @@
import{_ as a,o as i,c as e,ae as t}from"./chunks/framework.B1nRs-GM.js";const k=JSON.parse('{"title":"Памятка","description":"Короткий набор команд для регулярного обновления приложения от шаблона.","frontmatter":{"title":"Памятка","description":"Короткий набор команд для регулярного обновления приложения от шаблона."},"headers":[],"relativePath":"reference/cheatsheet.md","filePath":"reference/cheatsheet.md"}'),n={name:"reference/cheatsheet.md"};function l(h,s,p,d,c,o){return i(),e("div",null,[...s[0]||(s[0]=[t(`<div style="display:none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /template-sync-strategy/reference/cheatsheet.md for this page in Markdown format</div><h1 id="памятка" tabindex="-1">Памятка <a class="header-anchor" href="#памятка" aria-label="Permalink to &quot;Памятка&quot;"></a></h1><p>Рабочая схема:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>templates/master -&gt; template -&gt; sync/* -&gt; master</span></span></code></pre></div><h2 id="обновить-template" tabindex="-1">Обновить template <a class="header-anchor" href="#обновить-template" aria-label="Permalink to &quot;Обновить template&quot;"></a></h2><p>В репозитории приложения:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> pull</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --ff-only</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span></span></code></pre></div><p>Это подтягивает свежий шаблон из <code>templates/master</code> и пушит его в <code>origin/template</code>.</p><h2 id="создать-ветку-обновления" tabindex="-1">Создать ветку обновления <a class="header-anchor" href="#создать-ветку-обновления" aria-label="Permalink to &quot;Создать ветку обновления&quot;"></a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sync/update-template-vX</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/master</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> merge</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/template</span></span></code></pre></div><p>Если есть конфликты, решить их в этой же ветке:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> .</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> commit</span></span></code></pre></div><h2 id="запушить-sync-ветку" tabindex="-1">Запушить sync-ветку <a class="header-anchor" href="#запушить-sync-ветку" aria-label="Permalink to &quot;Запушить sync-ветку&quot;"></a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -u</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sync/update-template-vX</span></span></code></pre></div><h2 id="влить-через-ui" tabindex="-1">Влить через UI <a class="header-anchor" href="#влить-через-ui" aria-label="Permalink to &quot;Влить через UI&quot;"></a></h2><p>Создать PR/MR:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>source: sync/update-template-vX</span></span>
<span class="line"><span>target: master</span></span></code></pre></div><p>Важно:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>squash = off</span></span></code></pre></div><h2 id="проверка" tabindex="-1">Проверка <a class="header-anchor" href="#проверка" aria-label="Permalink to &quot;Проверка&quot;"></a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --graph</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --decorate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --max-count=30</span></span></code></pre></div><h2 id="суть-процесса" tabindex="-1">Суть процесса <a class="header-anchor" href="#суть-процесса" aria-label="Permalink to &quot;Суть процесса&quot;"></a></h2><ol><li>Обновить <code>template</code> из <code>templates/master</code>.</li><li>Создать <code>sync/*</code> от <code>origin/master</code>.</li><li>Влить <code>origin/template</code> в <code>sync/*</code>.</li><li>Решить конфликты, если есть.</li><li>Запушить <code>sync/*</code>.</li><li>Через UI влить <code>sync/* -&gt; master</code>.</li></ol>`,23)])])}const g=a(n,[["render",l]]);export{k as __pageData,g as default};

View File

@@ -1 +0,0 @@
import{_ as a,o as i,c as e,ae as t}from"./chunks/framework.B1nRs-GM.js";const k=JSON.parse('{"title":"Памятка","description":"Короткий набор команд для регулярного обновления приложения от шаблона.","frontmatter":{"title":"Памятка","description":"Короткий набор команд для регулярного обновления приложения от шаблона."},"headers":[],"relativePath":"reference/cheatsheet.md","filePath":"reference/cheatsheet.md"}'),n={name:"reference/cheatsheet.md"};function l(h,s,p,d,c,o){return i(),e("div",null,[...s[0]||(s[0]=[t("",23)])])}const g=a(n,[["render",l]]);export{k as __pageData,g as default};

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{_ as a,o as t,c as r,ae as s}from"./chunks/framework.B1nRs-GM.js";const m=JSON.parse('{"title":"Глоссарий","description":"Термины, которые используются в Template Sync Strategy.","frontmatter":{"title":"Глоссарий","description":"Термины, которые используются в Template Sync Strategy."},"headers":[],"relativePath":"reference/glossary.md","filePath":"reference/glossary.md"}'),i={name:"reference/glossary.md"};function o(l,e,p,n,d,h){return t(),r("div",null,[...e[0]||(e[0]=[s("",24)])])}const u=a(i,[["render",o]]);export{m as __pageData,u as default};

View File

@@ -1,9 +0,0 @@
import{_ as i,o as a,c as t,ae as e}from"./chunks/framework.B1nRs-GM.js";const g=JSON.parse('{"title":"Troubleshooting","description":"Типовые ошибки при обновлении проекта от шаблона и способы диагностики.","frontmatter":{"title":"Troubleshooting","description":"Типовые ошибки при обновлении проекта от шаблона и способы диагностики."},"headers":[],"relativePath":"reference/troubleshooting.md","filePath":"reference/troubleshooting.md"}'),n={name:"reference/troubleshooting.md"};function l(h,s,p,k,r,o){return a(),t("div",null,[...s[0]||(s[0]=[e(`<div style="display:none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /template-sync-strategy/reference/troubleshooting.md for this page in Markdown format</div><h1 id="troubleshooting" tabindex="-1">Troubleshooting <a class="header-anchor" href="#troubleshooting" aria-label="Permalink to &quot;Troubleshooting&quot;"></a></h1><h2 id="fatal-отказ-слияния-несвязанных-истории-изменении" tabindex="-1">fatal: отказ слияния несвязанных историй изменений <a class="header-anchor" href="#fatal-отказ-слияния-несвязанных-истории-изменении" aria-label="Permalink to &quot;fatal: отказ слияния несвязанных историй изменений&quot;"></a></h2><p>Ошибка:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>fatal: отказ слияния несвязанных историй изменений</span></span></code></pre></div><p>Причина: <code>master</code> приложения не был создан от <code>template</code>, поэтому у веток нет общего предка.</p><p>Решение: выполнить одноразовую миграцию через <code>sync/bootstrap-template</code> по инструкции <a href="./../setup/existing-master-migration">Миграция существующего master</a>.</p><p>Коротко:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sync/bootstrap-template</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/master</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> merge</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --allow-unrelated-histories</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/template</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -u</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sync/bootstrap-template</span></span></code></pre></div><h2 id="ff-only-падает-на-template" tabindex="-1">--ff-only падает на template <a class="header-anchor" href="#ff-only-падает-на-template" aria-label="Permalink to &quot;--ff-only падает на template&quot;"></a></h2><p>Ошибка возникает при команде:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> merge</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --ff-only</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates/master</span></span></code></pre></div><p>Причина: в <code>template</code> появились коммиты, которых нет в шаблоне. Значит ветка перестала быть чистым слепком.</p><p>Что проверить:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --graph</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --decorate</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates/master..template</span></span></code></pre></div><p>Решение зависит от причины. Не продолжайте обновление, пока не станет понятно, какие локальные коммиты попали в <code>template</code>.</p><h2 id="пустои-diff-в-sync-ветке" tabindex="-1">Пустой diff в sync-ветке <a class="header-anchor" href="#пустои-diff-в-sync-ветке" aria-label="Permalink to &quot;Пустой diff в sync-ветке&quot;"></a></h2><p>Симптом:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> diff</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --stat</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/master...HEAD</span></span></code></pre></div><p>не показывает изменений.</p><p>Возможные причины:</p><ul><li>в шаблоне нет новых изменений;</li><li><code>origin/template</code> не был обновлён;</li><li><code>origin/template</code> не был влит в <code>sync/*</code>;</li><li>sync-ветка создана не от актуального <code>origin/master</code>.</li></ul><p>Что проверить:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/template</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates/master</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --graph</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --decorate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --max-count=50</span></span></code></pre></div><h2 id="случаино-включили-squash" tabindex="-1">Случайно включили squash <a class="header-anchor" href="#случаино-включили-squash" aria-label="Permalink to &quot;Случайно включили squash&quot;"></a></h2><p>Если sync-PR/MR уже влит squash-merge, история шаблона могла не сохраниться как нормальная merge-связь.</p><p>Что сделать:</p><ul><li>зафиксировать факт в описании проекта;</li><li>проверить, видит ли Git последующие обновления шаблона без повторного применения старых изменений;</li><li>при следующем обновлении внимательно смотреть diff и конфликты;</li><li>для будущих sync-PR/MR отключить squash.</li></ul><p>Если ситуация стала неуправляемой, может потребоваться отдельная техническая миграция истории.</p><h2 id="cannot-run-less" tabindex="-1">cannot run less <a class="header-anchor" href="#cannot-run-less" aria-label="Permalink to &quot;cannot run less&quot;"></a></h2><p>Ошибка:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>cannot run less</span></span></code></pre></div><p>Причина: Git пытается открыть pager <code>less</code>, которого нет в системе.</p><p>Решение: использовать <code>git --no-pager</code>:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --graph</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --decorate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --max-count=50</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> diff</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template...master</span></span></code></pre></div>`,35)])])}const F=i(n,[["render",l]]);export{g as __pageData,F as default};

View File

@@ -1 +0,0 @@
import{_ as i,o as a,c as t,ae as e}from"./chunks/framework.B1nRs-GM.js";const g=JSON.parse('{"title":"Troubleshooting","description":"Типовые ошибки при обновлении проекта от шаблона и способы диагностики.","frontmatter":{"title":"Troubleshooting","description":"Типовые ошибки при обновлении проекта от шаблона и способы диагностики."},"headers":[],"relativePath":"reference/troubleshooting.md","filePath":"reference/troubleshooting.md"}'),n={name:"reference/troubleshooting.md"};function l(h,s,p,k,r,o){return a(),t("div",null,[...s[0]||(s[0]=[e("",35)])])}const F=i(n,[["render",l]]);export{g as __pageData,F as default};

View File

@@ -1,18 +0,0 @@
import{_ as a,o as i,c as t,ae as e}from"./chunks/framework.B1nRs-GM.js";const F=JSON.parse('{"title":"Новый проект от шаблона","description":"Старт нового приложения от шаблонного репозитория с правильной историей веток.","frontmatter":{"title":"Новый проект от шаблона","description":"Старт нового приложения от шаблонного репозитория с правильной историей веток."},"headers":[],"relativePath":"setup/clean-repository.md","filePath":"setup/clean-repository.md"}'),p={name:"setup/clean-repository.md"};function n(l,s,h,k,d,r){return i(),t("div",null,[...s[0]||(s[0]=[e(`<div style="display:none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /template-sync-strategy/setup/clean-repository.md for this page in Markdown format</div><h1 id="новыи-проект-от-шаблона" tabindex="-1">Новый проект от шаблона <a class="header-anchor" href="#новыи-проект-от-шаблона" aria-label="Permalink to &quot;Новый проект от шаблона&quot;"></a></h1><p>Этот сценарий подходит, когда репозиторий приложения ещё пустой или его можно безопасно пересоздать от шаблона.</p><p>Целевая модель:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>templates/master -&gt; template -&gt; sync/* -&gt; master</span></span></code></pre></div><h2 id="условия" tabindex="-1">Условия <a class="header-anchor" href="#условия" aria-label="Permalink to &quot;Условия&quot;"></a></h2><p>Есть два репозитория:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>template repo = репозиторий шаблона</span></span>
<span class="line"><span>app repo = репозиторий приложения</span></span></code></pre></div><p>В обоих репозиториях основная ветка называется <code>master</code>.</p><h2 id="подготовить-шаблон" tabindex="-1">Подготовить шаблон <a class="header-anchor" href="#подготовить-шаблон" aria-label="Permalink to &quot;Подготовить шаблон&quot;"></a></h2><p>В репозитории шаблона:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">cd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /path/to/template-repo</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> master</span></span></code></pre></div><p>Если это пустой репозиторий, добавьте первый файл и запушьте <code>master</code>:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">printf</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;# Template Repository\\n\\nBase template version: v1\\n&quot;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> README.md</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> README.md</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> commit</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -m</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;docs: добавить базовый шаблон&quot;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -u</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> master</span></span></code></pre></div><h2 id="подключить-шаблон-в-приложении" tabindex="-1">Подключить шаблон в приложении <a class="header-anchor" href="#подключить-шаблон-в-приложении" aria-label="Permalink to &quot;Подключить шаблон в приложении&quot;"></a></h2><p>В репозитории приложения:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">cd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /path/to/app-repo</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> remote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">template-repo-ur</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">l</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span></span></code></pre></div><p>Создайте ветку <code>template</code> от шаблона:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates/master</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -u</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template</span></span></code></pre></div><p>Создайте ветку приложения <code>master</code> от <code>template</code>:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> master</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template</span></span></code></pre></div><p>Добавьте слой приложения:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">mkdir</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> app</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">printf</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;Application code v1\\n&quot;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &gt;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> app/app.txt</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> app/app.txt</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> commit</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -m</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;feat: добавить слой приложения&quot;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -u</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> master</span></span></code></pre></div><p>После этого история выглядит так:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>template: T1</span></span>
<span class="line"><span>master: T1---A1</span></span></code></pre></div><p>Где <code>T1</code> — коммит шаблона, а <code>A1</code> — коммит приложения.</p><h2 id="настроить-pull-и-push-для-template" tabindex="-1">Настроить pull и push для template <a class="header-anchor" href="#настроить-pull-и-push-для-template" aria-label="Permalink to &quot;Настроить pull и push для template&quot;"></a></h2><p>Можно сделать так, чтобы на ветке <code>template</code>:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>git pull тянул из templates/master</span></span>
<span class="line"><span>git push пушил в origin/template</span></span></code></pre></div><p>Команды:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> branch.template.remote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> branch.template.merge</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> refs/heads/master</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> branch.template.pushRemote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span></span></code></pre></div><p>Дополнительно можно запретить случайный push в репозиторий шаблона:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> remote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> set-url</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --push</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> DISABLED</span></span></code></pre></div><h2 id="дальше" tabindex="-1">Дальше <a class="header-anchor" href="#дальше" aria-label="Permalink to &quot;Дальше&quot;"></a></h2><p>После первичной настройки постоянные ветки такие:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>template = чистый шаблон</span></span>
<span class="line"><span>master = приложение</span></span></code></pre></div><p>Обновления шаблона выполняются через временные ветки <code>sync/*</code> по инструкции <a href="./../workflows/update-template">Обычное обновление шаблона</a>.</p>`,37)])])}const c=a(p,[["render",n]]);export{F as __pageData,c as default};

View File

@@ -1 +0,0 @@
import{_ as a,o as i,c as t,ae as e}from"./chunks/framework.B1nRs-GM.js";const F=JSON.parse('{"title":"Новый проект от шаблона","description":"Старт нового приложения от шаблонного репозитория с правильной историей веток.","frontmatter":{"title":"Новый проект от шаблона","description":"Старт нового приложения от шаблонного репозитория с правильной историей веток."},"headers":[],"relativePath":"setup/clean-repository.md","filePath":"setup/clean-repository.md"}'),p={name:"setup/clean-repository.md"};function n(l,s,h,k,d,r){return i(),t("div",null,[...s[0]||(s[0]=[e("",37)])])}const c=a(p,[["render",n]]);export{F as __pageData,c as default};

View File

@@ -1,17 +0,0 @@
import{_ as a,o as i,c as t,ae as e}from"./chunks/framework.B1nRs-GM.js";const g=JSON.parse('{"title":"Миграция существующего master","description":"Как одноразово связать master приложения с историей шаблона, если проект был создан отдельно.","frontmatter":{"title":"Миграция существующего master","description":"Как одноразово связать master приложения с историей шаблона, если проект был создан отдельно."},"headers":[],"relativePath":"setup/existing-master-migration.md","filePath":"setup/existing-master-migration.md"}'),p={name:"setup/existing-master-migration.md"};function n(h,s,l,k,d,r){return i(),t("div",null,[...s[0]||(s[0]=[e(`<div style="display:none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /template-sync-strategy/setup/existing-master-migration.md for this page in Markdown format</div><h1 id="миграция-существующего-master" tabindex="-1">Миграция существующего master <a class="header-anchor" href="#миграция-существующего-master" aria-label="Permalink to &quot;Миграция существующего master&quot;"></a></h1><p>Этот сценарий нужен, если в репозитории приложения уже есть <code>master</code>, но он был создан не от шаблона.</p><h2 id="проблема" tabindex="-1">Проблема <a class="header-anchor" href="#проблема" aria-label="Permalink to &quot;Проблема&quot;"></a></h2><p>Если <code>master</code> приложения и <code>template</code> имеют разные корневые коммиты, Git видит две несвязанные истории.</p><p>Плохое состояние:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>template: T1---T2---T3</span></span>
<span class="line"><span></span></span>
<span class="line"><span>master: A1---A2</span></span></code></pre></div><p>При попытке выполнить обычный merge Git может ответить:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>fatal: отказ слияния несвязанных историй изменений</span></span></code></pre></div><p>Это означает, что у веток нет общего предка.</p><h2 id="цель-миграции" tabindex="-1">Цель миграции <a class="header-anchor" href="#цель-миграции" aria-label="Permalink to &quot;Цель миграции&quot;"></a></h2><p>Нужно один раз связать истории, чтобы дальше обновления шаблона шли обычным merge-процессом.</p><p>После миграции история будет выглядеть примерно так:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>template: T1---T2---T3</span></span>
<span class="line"><span> \\</span></span>
<span class="line"><span>master: A1---A2-----M</span></span></code></pre></div><p>Где <code>M</code> — одноразовый merge-коммит, который связал историю приложения с историей шаблона.</p><h2 id="подключить-репозитории-шаблона" tabindex="-1">Подключить репозиторий шаблона <a class="header-anchor" href="#подключить-репозитории-шаблона" aria-label="Permalink to &quot;Подключить репозиторий шаблона&quot;"></a></h2><p>В репозитории приложения:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">cd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /path/to/app-repo</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> remote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">template-repo-ur</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">l</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span></span></code></pre></div><p>Если remote <code>templates</code> уже существует:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span></span></code></pre></div><h2 id="создать-или-обновить-template" tabindex="-1">Создать или обновить template <a class="header-anchor" href="#создать-или-обновить-template" aria-label="Permalink to &quot;Создать или обновить template&quot;"></a></h2><p>Если ветки <code>template</code> ещё нет:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates/master</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -u</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template</span></span></code></pre></div><p>Если ветка <code>template</code> уже есть:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> merge</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --ff-only</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates/master</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template</span></span></code></pre></div><p>Опционально настройте удобное поведение <code>pull</code> и <code>push</code>:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> branch.template.remote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> branch.template.merge</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> refs/heads/master</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> config</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> branch.template.pushRemote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> remote</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> set-url</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --push</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> DISABLED</span></span></code></pre></div><h2 id="связать-master-с-template" tabindex="-1">Связать master с template <a class="header-anchor" href="#связать-master-с-template" aria-label="Permalink to &quot;Связать master с template&quot;"></a></h2><p>Создайте временную ветку от текущего приложения:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sync/bootstrap-template</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/master</span></span></code></pre></div><p>Слейте шаблон с разрешением несвязанных историй:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> merge</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --allow-unrelated-histories</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/template</span></span></code></pre></div><p>Если есть конфликты, решите их в ветке <code>sync/bootstrap-template</code>:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> .</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> commit</span></span></code></pre></div><p>Если конфликтов не было, Git сам создаст merge-коммит.</p><p>Запушьте ветку:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -u</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sync/bootstrap-template</span></span></code></pre></div><p>Дальше через UI или локально смержите:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>sync/bootstrap-template -&gt; master</span></span></code></pre></div><h2 id="что-проверить-перед-merge" tabindex="-1">Что проверить перед merge <a class="header-anchor" href="#что-проверить-перед-merge" aria-label="Permalink to &quot;Что проверить перед merge&quot;"></a></h2><p>Посмотрите граф истории:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --graph</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --decorate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --max-count=50</span></span></code></pre></div><p>Убедитесь, что <code>sync/bootstrap-template</code> содержит и историю приложения, и историю шаблона.</p><p>Посмотрите итоговый diff:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> diff</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/master...sync/bootstrap-template</span></span></code></pre></div><h2 id="когда-миграцию-делать-не-стоит" tabindex="-1">Когда миграцию делать не стоит <a class="header-anchor" href="#когда-миграцию-делать-не-стоит" aria-label="Permalink to &quot;Когда миграцию делать не стоит&quot;"></a></h2><p>Не стоит связывать истории, если приложение только что создано и его можно безопасно пересоздать от шаблона.</p><p>Для нового проекта лучше сделать чистый старт по инструкции <a href="./clean-repository">Новый проект от шаблона</a>.</p>`,48)])])}const F=a(p,[["render",n]]);export{g as __pageData,F as default};

View File

@@ -1 +0,0 @@
import{_ as a,o as i,c as t,ae as e}from"./chunks/framework.B1nRs-GM.js";const g=JSON.parse('{"title":"Миграция существующего master","description":"Как одноразово связать master приложения с историей шаблона, если проект был создан отдельно.","frontmatter":{"title":"Миграция существующего master","description":"Как одноразово связать master приложения с историей шаблона, если проект был создан отдельно."},"headers":[],"relativePath":"setup/existing-master-migration.md","filePath":"setup/existing-master-migration.md"}'),p={name:"setup/existing-master-migration.md"};function n(h,s,l,k,d,r){return i(),t("div",null,[...s[0]||(s[0]=[e("",48)])])}const F=a(p,[["render",n]]);export{g as __pageData,F as default};

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +0,0 @@
import{_ as a,o as e,c as i,ae as t}from"./chunks/framework.B1nRs-GM.js";const k=JSON.parse('{"title":"Решение конфликтов","description":"Почему конфликты при обновлении шаблона должны решаться только в sync-ветках.","frontmatter":{"title":"Решение конфликтов","description":"Почему конфликты при обновлении шаблона должны решаться только в sync-ветках."},"headers":[],"relativePath":"workflows/resolve-conflicts.md","filePath":"workflows/resolve-conflicts.md"}'),n={name:"workflows/resolve-conflicts.md"};function l(p,s,o,h,d,c){return e(),i("div",null,[...s[0]||(s[0]=[t(`<div style="display:none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /template-sync-strategy/workflows/resolve-conflicts.md for this page in Markdown format</div><h1 id="решение-конфликтов" tabindex="-1">Решение конфликтов <a class="header-anchor" href="#решение-конфликтов" aria-label="Permalink to &quot;Решение конфликтов&quot;"></a></h1><p>Конфликт при обновлении шаблона — нормальная ситуация. Важно не то, что конфликт возник, а где он возник.</p><p>Правильное место для конфликтов — временная ветка <code>sync/*</code>.</p><h2 id="пример" tabindex="-1">Пример <a class="header-anchor" href="#пример" aria-label="Permalink to &quot;Пример&quot;"></a></h2><p>Шаблон поменял строку в <code>README.md</code>:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>Base template version: template-conflict-v10</span></span></code></pre></div><p>Приложение поменяло ту же строку иначе:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>Base template version: application-conflict-v10</span></span></code></pre></div><p>При merge <code>origin/template</code> в <code>sync/update-template-v10</code> появится конфликт:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD</span></span>
<span class="line"><span>Base template version: application-conflict-v10</span></span>
<span class="line"><span>=======</span></span>
<span class="line"><span>Base template version: template-conflict-v10</span></span>
<span class="line"><span>&gt;&gt;&gt;&gt;&gt;&gt;&gt; origin/template</span></span></code></pre></div><p>Это правильное место конфликта: <code>master</code> ещё не изменён, <code>template</code> остаётся чистой, а итоговое решение можно проверить в PR/MR.</p><h2 id="как-решать" tabindex="-1">Как решать <a class="header-anchor" href="#как-решать" aria-label="Permalink to &quot;Как решать&quot;"></a></h2><ol><li>Оставайтесь в ветке <code>sync/*</code>.</li><li>Разберите конфликт по смыслу: что должно остаться в приложении после обновления шаблона.</li><li>Удалите conflict markers.</li><li>Проверьте проект локально.</li><li>Закоммитьте результат.</li></ol><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> status</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> .</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> commit</span></span></code></pre></div><h2 id="что-нельзя-делать" tabindex="-1">Что нельзя делать <a class="header-anchor" href="#что-нельзя-делать" aria-label="Permalink to &quot;Что нельзя делать&quot;"></a></h2><p>Нельзя переносить conflict resolve в <code>template</code>.</p><p><code>template</code> должна совпадать с шаблоном. Если решение конфликта попадёт туда, она перестанет быть эталоном и дальнейшие обновления станут менее предсказуемыми.</p><p>Нельзя решать конфликт прямо в <code>master</code>, потому что основная ветка приложения должна получать только проверенный результат через PR/MR.</p><h2 id="что-проверить-после-resolve" tabindex="-1">Что проверить после resolve <a class="header-anchor" href="#что-проверить-после-resolve" aria-label="Permalink to &quot;Что проверить после resolve&quot;"></a></h2><p>Посмотрите статус:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> status</span></span></code></pre></div><p>Посмотрите diff относительно текущего приложения:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> diff</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/master...HEAD</span></span></code></pre></div><p>Посмотрите граф:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --graph</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --decorate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --max-count=50</span></span></code></pre></div>`,26)])])}const g=a(n,[["render",l]]);export{k as __pageData,g as default};

View File

@@ -1 +0,0 @@
import{_ as a,o as e,c as i,ae as t}from"./chunks/framework.B1nRs-GM.js";const k=JSON.parse('{"title":"Решение конфликтов","description":"Почему конфликты при обновлении шаблона должны решаться только в sync-ветках.","frontmatter":{"title":"Решение конфликтов","description":"Почему конфликты при обновлении шаблона должны решаться только в sync-ветках."},"headers":[],"relativePath":"workflows/resolve-conflicts.md","filePath":"workflows/resolve-conflicts.md"}'),n={name:"workflows/resolve-conflicts.md"};function l(p,s,o,h,d,c){return e(),i("div",null,[...s[0]||(s[0]=[t("",26)])])}const g=a(n,[["render",l]]);export{k as __pageData,g as default};

View File

@@ -1,9 +0,0 @@
import{_ as a,o as i,c as e,ae as t}from"./chunks/framework.B1nRs-GM.js";const g=JSON.parse('{"title":"Review и merge","description":"Как проверять и вливать sync-ветку с обновлением шаблона в master приложения.","frontmatter":{"title":"Review и merge","description":"Как проверять и вливать sync-ветку с обновлением шаблона в master приложения."},"headers":[],"relativePath":"workflows/review-and-merge.md","filePath":"workflows/review-and-merge.md"}'),n={name:"workflows/review-and-merge.md"};function p(l,s,h,r,d,o){return i(),e("div",null,[...s[0]||(s[0]=[t(`<div style="display:none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /template-sync-strategy/workflows/review-and-merge.md for this page in Markdown format</div><h1 id="review-и-merge" tabindex="-1">Review и merge <a class="header-anchor" href="#review-и-merge" aria-label="Permalink to &quot;Review и merge&quot;"></a></h1><p>После подготовки <code>sync/*</code> ветки обновление шаблона должно попасть в <code>master</code> через PR/MR.</p><h2 id="создать-pr-mr" tabindex="-1">Создать PR/MR <a class="header-anchor" href="#создать-pr-mr" aria-label="Permalink to &quot;Создать PR/MR&quot;"></a></h2><p>Параметры:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>source: sync/update-template-vX</span></span>
<span class="line"><span>target: master</span></span></code></pre></div><p>Цель review — увидеть:</p><ul><li>какие изменения пришли из шаблона;</li><li>какие конфликтные решения были сделаны в <code>sync/*</code>;</li><li>не попали ли в обновление лишние изменения приложения;</li><li>проходят ли проверки проекта.</li></ul><h2 id="настроики-merge" tabindex="-1">Настройки merge <a class="header-anchor" href="#настроики-merge" aria-label="Permalink to &quot;Настройки merge&quot;"></a></h2><p>Для sync-PR/MR важно:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>squash = off</span></span>
<span class="line"><span>fast-forward merge = хорошо</span></span>
<span class="line"><span>merge commit = допустимо</span></span>
<span class="line"><span>squash merge = нельзя</span></span></code></pre></div><p>Squash нельзя использовать, потому что он может уничтожить связь истории <code>master</code> с историей <code>template</code>. Особенно это критично после миграционного <code>sync/bootstrap-template</code>.</p><h2 id="проверки-перед-merge" tabindex="-1">Проверки перед merge <a class="header-anchor" href="#проверки-перед-merge" aria-label="Permalink to &quot;Проверки перед merge&quot;"></a></h2><p>Проверьте граф истории:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --graph</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --decorate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --all</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --max-count=50</span></span></code></pre></div><p>Проверьте итоговый diff:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> diff</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/master...sync/update-template-vX</span></span></code></pre></div><p>Проверьте проект обычными командами конкретного приложения, например:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">npm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> lint</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">npm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> build</span></span></code></pre></div><h2 id="после-merge" tabindex="-1">После merge <a class="header-anchor" href="#после-merge" aria-label="Permalink to &quot;После merge&quot;"></a></h2><p>После успешного merge в <code>master</code> можно удалить временную ветку:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> branch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sync/update-template-vX</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --delete</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sync/update-template-vX</span></span></code></pre></div><p>Проверьте, что <code>master</code> теперь содержит обновление шаблона:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/template..origin/master</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> diff</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/template...origin/master</span></span></code></pre></div>`,24)])])}const c=a(n,[["render",p]]);export{g as __pageData,c as default};

View File

@@ -1 +0,0 @@
import{_ as a,o as i,c as e,ae as t}from"./chunks/framework.B1nRs-GM.js";const g=JSON.parse('{"title":"Review и merge","description":"Как проверять и вливать sync-ветку с обновлением шаблона в master приложения.","frontmatter":{"title":"Review и merge","description":"Как проверять и вливать sync-ветку с обновлением шаблона в master приложения."},"headers":[],"relativePath":"workflows/review-and-merge.md","filePath":"workflows/review-and-merge.md"}'),n={name:"workflows/review-and-merge.md"};function p(l,s,h,r,d,o){return i(),e("div",null,[...s[0]||(s[0]=[t("",24)])])}const c=a(n,[["render",p]]);export{g as __pageData,c as default};

View File

@@ -1,17 +0,0 @@
import{_ as a,o as i,c as t,ae as e}from"./chunks/framework.B1nRs-GM.js";const c=JSON.parse('{"title":"Обычное обновление шаблона","description":"Повторяемый процесс доставки изменений шаблона в приложение после первичной настройки.","frontmatter":{"title":"Обычное обновление шаблона","description":"Повторяемый процесс доставки изменений шаблона в приложение после первичной настройки."},"headers":[],"relativePath":"workflows/update-template.md","filePath":"workflows/update-template.md"}'),p={name:"workflows/update-template.md"};function n(l,s,h,k,d,r){return i(),t("div",null,[...s[0]||(s[0]=[e(`<div style="display:none;" hidden="true" aria-hidden="true">Are you an LLM? You can read better optimized documentation at /template-sync-strategy/workflows/update-template.md for this page in Markdown format</div><h1 id="обычное-обновление-шаблона" tabindex="-1">Обычное обновление шаблона <a class="header-anchor" href="#обычное-обновление-шаблона" aria-label="Permalink to &quot;Обычное обновление шаблона&quot;"></a></h1><p>Эта инструкция подходит после любого стартового сценария:</p><ul><li><a href="./../setup/clean-repository">Новый проект от шаблона</a>.</li><li><a href="./../setup/existing-master-migration">Миграция существующего master</a>.</li></ul><p>Целевой маршрут:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>templates/master -&gt; template -&gt; sync/* -&gt; master</span></span></code></pre></div><h2 id="_1-обновить-слепок-шаблона" tabindex="-1">1. Обновить слепок шаблона <a class="header-anchor" href="#_1-обновить-слепок-шаблона" aria-label="Permalink to &quot;1. Обновить слепок шаблона&quot;"></a></h2><p>В репозитории приложения:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">cd</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> /path/to/app-repo</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> pull</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --ff-only</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span></span></code></pre></div><p>Этот вариант работает, если для ветки <code>template</code> настроено:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>pull из templates/master</span></span>
<span class="line"><span>push в origin/template</span></span></code></pre></div><p>Явная форма без зависимости от tracking-настроек:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> merge</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --ff-only</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates/master</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> template</span></span></code></pre></div><p>Если <code>--ff-only</code> падает, значит <code>template</code> перестал быть чистым слепком шаблона. Остановитесь и разберите причину до продолжения.</p><p>Проверьте, что <code>origin/template</code> обновился до шаблона:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/template</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> log</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --oneline</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -1</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> templates/master</span></span></code></pre></div><p>Оба коммита должны совпадать.</p><h2 id="_2-создать-ветку-обновления-приложения" tabindex="-1">2. Создать ветку обновления приложения <a class="header-anchor" href="#_2-создать-ветку-обновления-приложения" aria-label="Permalink to &quot;2. Создать ветку обновления приложения&quot;"></a></h2><p>После обновления <code>template</code> создайте временную ветку от текущего приложения:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> fetch</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> switch</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -c</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sync/update-template-v2</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/master</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> merge</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/template</span></span></code></pre></div><p>Имя ветки можно менять под версию или дату:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>sync/update-template-v2</span></span>
<span class="line"><span>sync/update-template-2026-05-09</span></span>
<span class="line"><span>sync/update-template-1.8.0</span></span></code></pre></div><p>Проверьте, что временная ветка реально отличается от <code>origin/master</code> изменениями шаблона:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-pager</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> diff</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --stat</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin/master...HEAD</span></span></code></pre></div><p>Если diff пустой, значит обновлённый <code>origin/template</code> не был влит в <code>sync/*</code> ветку или в шаблоне нет новых изменений.</p><h2 id="_3-решить-конфликты" tabindex="-1">3. Решить конфликты <a class="header-anchor" href="#_3-решить-конфликты" aria-label="Permalink to &quot;3. Решить конфликты&quot;"></a></h2><p>Если есть конфликты, решайте их именно в <code>sync/*</code>.</p><p>После решения конфликтов:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> .</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> commit</span></span></code></pre></div><p>Если конфликтов не было, Git сам создаст merge-коммит или выполнит fast-forward, в зависимости от истории.</p><h2 id="_4-запушить-sync-ветку" tabindex="-1">4. Запушить sync-ветку <a class="header-anchor" href="#_4-запушить-sync-ветку" aria-label="Permalink to &quot;4. Запушить sync-ветку&quot;"></a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">git</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> push</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -u</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> origin</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> sync/update-template-v2</span></span></code></pre></div><p>Дальше откройте PR/MR:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>source: sync/update-template-v2</span></span>
<span class="line"><span>target: master</span></span></code></pre></div><p>Правила merge описаны в <a href="./review-and-merge">Review и merge</a>.</p>`,35)])])}const g=a(p,[["render",n]]);export{c as __pageData,g as default};

View File

@@ -1 +0,0 @@
import{_ as a,o as i,c as t,ae as e}from"./chunks/framework.B1nRs-GM.js";const c=JSON.parse('{"title":"Обычное обновление шаблона","description":"Повторяемый процесс доставки изменений шаблона в приложение после первичной настройки.","frontmatter":{"title":"Обычное обновление шаблона","description":"Повторяемый процесс доставки изменений шаблона в приложение после первичной настройки."},"headers":[],"relativePath":"workflows/update-template.md","filePath":"workflows/update-template.md"}'),p={name:"workflows/update-template.md"};function n(l,s,h,k,d,r){return i(),t("div",null,[...s[0]||(s[0]=[e("",35)])])}const g=a(p,[["render",n]]);export{c as __pageData,g as default};

File diff suppressed because one or more lines are too long

View File

@@ -1,72 +0,0 @@
---
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.

File diff suppressed because one or more lines are too long

View File

@@ -1,49 +0,0 @@
---
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` — эталонный слепок оригинального шаблона.
Если в неё попадает локальное решение конфликта или изменение приложения, она перестаёт отвечать на вопрос: “какая версия шаблона сейчас подключена к приложению?”.
После этого ломается главная граница ответственности: шаблон отдельно, приложение отдельно, конфликтная зона отдельно.

File diff suppressed because one or more lines are too long

View File

@@ -1,46 +0,0 @@
---
url: /template-sync-strategy/concepts/why.md
description: >-
Почему шаблону нужен процесс обновления, а не только быстрый старт нового
проекта.
---
# Зачем это нужно
Шаблон закрывает повторяющуюся техническую базу проекта: CI/CD, Dockerfile, зависимости, lint, build, структуру каталогов и базовую документацию.
Это снимает рутину на старте. Команде не нужно каждый раз заново собирать одинаковый технический каркас.
## Проблема после старта
Создать проект легко. Поддерживать 10-20 проектов сложнее.
Сначала проекты похожи. Потом они начинают расходиться:
* В одном проекте обновили CI, в другом забыли.
* В одном проекте Dockerfile остался из шаблона, в другом его локально поправили.
* В одном проекте зависимости уже свежие, в другом остались старые версии.
* В одном проекте изменения шаблона перенесли руками, в другом потеряли.
Без процесса обновления шаблон перестаёт быть общей основой. Он остаётся только способом быстро создать первый коммит.
## Что ломается без стратегии
Когда шаблон нельзя нормально обновлять:
* проекты начинают жить своей жизнью;
* граница между шаблоном и приложением теряется;
* обновления превращаются в ручное копирование;
* конфликты решаются прямо в рабочих ветках;
* становится непонятно, какой проект на какой версии шаблона;
* Git-история перестаёт быть источником правды.
Это особенно больно, когда приложений много. Для одного проекта ручной перенос ещё можно пережить. Для набора проектов нужен единый маршрут обновления.
## Цель стратегии
Стратегия не пытается убрать конфликты полностью. Она делает так, чтобы конфликты возникали в предсказуемом месте, проходили review и не ломали чистую ветку шаблона.
Главная формулировка:
> Шаблон должен обновляться так же контролируемо, как обычная фича: через ветку, проверку и PR/MR.

View File

@@ -1 +0,0 @@
{"concepts_model.md":"C805A9As","concepts_rules.md":"QraT4IhZ","concepts_why.md":"akfw90Fj","index.md":"C5Q_ZnE3","overview.md":"DOeHHuHO","reference_cheatsheet.md":"0TzKSaSb","reference_glossary.md":"DLD-b2Ke","reference_troubleshooting.md":"BrYSpYuW","setup_clean-repository.md":"CPqmBfph","setup_existing-master-migration.md":"BQ5VImS9","workflows_resolve-conflicts.md":"CujNWdsi","workflows_review-and-merge.md":"D5KhlAbu","workflows_update-template.md":"C8s1FFCq"}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +0,0 @@
# Template Sync Strategy
> Управляемое обновление проектов от шаблона
## Table of Contents
### Введение
- [Template Sync Strategy](/template-sync-strategy/overview.md): Управляемое обновление проектов от шаблона через чистую ветку template, временные sync-ветки и PR/MR.
- [Зачем это нужно](/template-sync-strategy/concepts/why.md): Почему шаблону нужен процесс обновления, а не только быстрый старт нового проекта.
- [Модель веток](/template-sync-strategy/concepts/model.md): Роли веток и remote в стратегии обновления проекта от шаблона.
- [Правила процесса](/template-sync-strategy/concepts/rules.md): Набор правил, который удерживает template чистой, а обновления шаблона контролируемыми.
### Настройка
- [Новый проект от шаблона](/template-sync-strategy/setup/clean-repository.md): Старт нового приложения от шаблонного репозитория с правильной историей веток.
- [Миграция существующего master](/template-sync-strategy/setup/existing-master-migration.md): Как одноразово связать master приложения с историей шаблона, если проект был создан отдельно.
### Рабочие процессы
- [Обычное обновление шаблона](/template-sync-strategy/workflows/update-template.md): Повторяемый процесс доставки изменений шаблона в приложение после первичной настройки.
- [Решение конфликтов](/template-sync-strategy/workflows/resolve-conflicts.md): Почему конфликты при обновлении шаблона должны решаться только в sync-ветках.
- [Review и merge](/template-sync-strategy/workflows/review-and-merge.md): Как проверять и вливать sync-ветку с обновлением шаблона в master приложения.
### Справочник
- [Памятка](/template-sync-strategy/reference/cheatsheet.md): Короткий набор команд для регулярного обновления приложения от шаблона.
- [Troubleshooting](/template-sync-strategy/reference/troubleshooting.md): Типовые ошибки при обновлении проекта от шаблона и способы диагностики.
- [Глоссарий](/template-sync-strategy/reference/glossary.md): Термины, которые используются в Template Sync Strategy.

File diff suppressed because one or more lines are too long

View File

@@ -1,49 +0,0 @@
---
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) — основные термины.

File diff suppressed because one or more lines are too long

View File

@@ -1,75 +0,0 @@
---
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`.

File diff suppressed because one or more lines are too long

View File

@@ -1,52 +0,0 @@
---
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`.

File diff suppressed because one or more lines are too long

View File

@@ -1,102 +0,0 @@
---
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
```

File diff suppressed because one or more lines are too long

View File

@@ -1,119 +0,0 @@
---
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).

File diff suppressed because one or more lines are too long

View File

@@ -1,146 +0,0 @@
---
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).

File diff suppressed because one or more lines are too long

View File

@@ -1,78 +0,0 @@
---
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
```

File diff suppressed because one or more lines are too long

View File

@@ -1,75 +0,0 @@
---
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
```

File diff suppressed because one or more lines are too long

View File

@@ -1,113 +0,0 @@
---
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).