chore: добавить сборку frontend-агента
- добавлен агент frontend-architect с манифестом и reference-картой - добавлен скрипт сборки архива агента в public/agents - добавлена сборка агентов в CI и Docker-сборку - исключены generated-директории public/agents и public/template-sync-strategy - удалены сгенерированные файлы Template Sync Strategy из git
This commit is contained in:
@@ -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*
|
||||
|
||||
@@ -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
2
.gitignore
vendored
@@ -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/*
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
189
agents/frontend-architect/scripts/build.ts
Normal file
189
agents/frontend-architect/scripts/build.ts
Normal 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();
|
||||
88
agents/frontend-architect/source/AGENT.md
Normal file
88
agents/frontend-architect/source/AGENT.md
Normal 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-совместимый вариант. Если правил недостаточно для решения, задай один уточняющий вопрос.
|
||||
17
agents/frontend-architect/source/manifest.json
Normal file
17
agents/frontend-architect/source/manifest.json
Normal 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"
|
||||
]
|
||||
}
|
||||
36
agents/frontend-architect/source/references.json
Normal file
36
agents/frontend-architect/source/references.json
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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>
|
||||
@@ -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
@@ -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 "Модель веток""></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 -> template -> sync/* -> 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 "templates/master""></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;"> <</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;">></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 "template""></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 "master""></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 "sync/*""></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 "Почему нужен отдельный sync-слой""></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};
|
||||
@@ -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};
|
||||
@@ -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 "Правила процесса""></a></h1><p>Небольшой набор правил удерживает схему чистой.</p><h2 id="делаем" tabindex="-1">Делаем <a class="header-anchor" href="#делаем" aria-label="Permalink to "Делаем""></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/* -> 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 "Не делаем""></a></h2><ul><li>Не правим <code>template</code> руками.</li><li>Не коммитим изменения приложения в <code>template</code>.</li><li>Не мержим <code>template -> master</code> напрямую.</li><li>Не решаем конфликты в <code>master</code>.</li><li>Не включаем squash для <code>sync/* -> master</code>.</li></ul><h2 id="почему-squash-нельзя" tabindex="-1">Почему squash нельзя <a class="header-anchor" href="#почему-squash-нельзя" aria-label="Permalink to "Почему squash нельзя""></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 "Почему template нельзя пачкать""></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};
|
||||
@@ -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};
|
||||
@@ -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 "Зачем это нужно""></a></h1><p>Шаблон закрывает повторяющуюся техническую базу проекта: CI/CD, Dockerfile, зависимости, lint, build, структуру каталогов и базовую документацию.</p><p>Это снимает рутину на старте. Команде не нужно каждый раз заново собирать одинаковый технический каркас.</p><h2 id="проблема-после-старта" tabindex="-1">Проблема после старта <a class="header-anchor" href="#проблема-после-старта" aria-label="Permalink to "Проблема после старта""></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 "Что ломается без стратегии""></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 "Цель стратегии""></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};
|
||||
@@ -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
@@ -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};
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -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};
|
||||
@@ -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 "Памятка""></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 -> template -> sync/* -> master</span></span></code></pre></div><h2 id="обновить-template" tabindex="-1">Обновить template <a class="header-anchor" href="#обновить-template" aria-label="Permalink to "Обновить template""></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 "Создать ветку обновления""></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 "Запушить sync-ветку""></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 "Влить через UI""></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 "Проверка""></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 "Суть процесса""></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/* -> master</code>.</li></ol>`,23)])])}const g=a(n,[["render",l]]);export{k as __pageData,g as default};
|
||||
@@ -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
@@ -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};
|
||||
@@ -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 "Troubleshooting""></a></h1><h2 id="fatal-отказ-слияния-несвязанных-истории-изменении" tabindex="-1">fatal: отказ слияния несвязанных историй изменений <a class="header-anchor" href="#fatal-отказ-слияния-несвязанных-истории-изменении" aria-label="Permalink to "fatal: отказ слияния несвязанных историй изменений""></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 "--ff-only падает на template""></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 "Пустой diff в sync-ветке""></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 "Случайно включили squash""></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 "cannot run less""></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};
|
||||
@@ -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};
|
||||
@@ -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 "Новый проект от шаблона""></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 -> template -> sync/* -> master</span></span></code></pre></div><h2 id="условия" tabindex="-1">Условия <a class="header-anchor" href="#условия" aria-label="Permalink to "Условия""></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 "Подготовить шаблон""></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;"> "# Template Repository\\n\\nBase template version: v1\\n"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ></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;"> "docs: добавить базовый шаблон"</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 "Подключить шаблон в приложении""></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;"> <</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;">></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;"> "Application code v1\\n"</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ></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;"> "feat: добавить слой приложения"</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 "Настроить pull и push для template""></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 "Дальше""></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};
|
||||
@@ -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};
|
||||
@@ -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 "Миграция существующего master""></a></h1><p>Этот сценарий нужен, если в репозитории приложения уже есть <code>master</code>, но он был создан не от шаблона.</p><h2 id="проблема" tabindex="-1">Проблема <a class="header-anchor" href="#проблема" aria-label="Permalink to "Проблема""></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 "Цель миграции""></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 "Подключить репозиторий шаблона""></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;"> <</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;">></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 "Создать или обновить template""></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 "Связать master с template""></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 -> master</span></span></code></pre></div><h2 id="что-проверить-перед-merge" tabindex="-1">Что проверить перед merge <a class="header-anchor" href="#что-проверить-перед-merge" aria-label="Permalink to "Что проверить перед merge""></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 "Когда миграцию делать не стоит""></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};
|
||||
@@ -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
@@ -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 "Решение конфликтов""></a></h1><p>Конфликт при обновлении шаблона — нормальная ситуация. Важно не то, что конфликт возник, а где он возник.</p><p>Правильное место для конфликтов — временная ветка <code>sync/*</code>.</p><h2 id="пример" tabindex="-1">Пример <a class="header-anchor" href="#пример" aria-label="Permalink to "Пример""></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><<<<<<< 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>>>>>>>> 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 "Как решать""></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 "Что нельзя делать""></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 "Что проверить после resolve""></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};
|
||||
@@ -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};
|
||||
@@ -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 "Review и merge""></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 "Создать PR/MR""></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 "Настройки merge""></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 "Проверки перед merge""></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 "После merge""></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};
|
||||
@@ -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};
|
||||
@@ -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 "Обычное обновление шаблона""></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 -> template -> sync/* -> master</span></span></code></pre></div><h2 id="_1-обновить-слепок-шаблона" tabindex="-1">1. Обновить слепок шаблона <a class="header-anchor" href="#_1-обновить-слепок-шаблона" aria-label="Permalink to "1. Обновить слепок шаблона""></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 "2. Создать ветку обновления приложения""></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 "3. Решить конфликты""></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 "4. Запушить sync-ветку""></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};
|
||||
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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).
|
||||
Reference in New Issue
Block a user