chore: adopt linear git model without release-to-main branch #34

Closed
opened 2026-10-17 13:57:07 +03:00 by codex-bot · 2 comments
Owner

Контекст

Текущий процесс (README.md:154-211) описывает release-ветку от develop, ff-only merge в main и обратную синхронизацию PR main → develop. Back-merge существует только ради коммита chore(release): X.Y.Z, который создаётся на release-ветке и потому отсутствует в develop. Он оставляет merge-коммит в develop при каждом релизе.

Gitea при этом не принуждает линейность: во всех пяти репозиториях allow_merge_commits: true и default_merge_style: merge. В истории main присутствуют merge-коммиты (d2d1092, 3321d9d, ed8221a в root; 774e58e в backend).

Проверено на момент создания Issue: origin/main является предком origin/develop во всех пяти репозиториях. Переход возможен без переписывания истории.

Решение

Модель:

feature/* --squash|rebase-merge--> develop --ff-only--> main --> tag vX.Y.Z

Инвариант: origin/main всегда предок origin/develop.

Релиз:

  1. git fetch origin --tags; ветка release/X.Y.Z от свежего develop
  2. npm run release:preview, затем npm run release:prepare
  3. PR release/X.Y.Z → develop, title chore(release): X.Y.Z, ff-only merge
  4. PR develop → main, тот же title, ff-only merge
  5. git tag -a vX.Y.Z <main-sha> -m "Release X.Y.Z"; git push origin refs/tags/vX.Y.Z

Убирается: back-merge main → develop, cherry-pick, rebase develop, release/hotfix-* от main.

Не меняется: .release-it.json (requireBranch: "release/*" работает без правок), commitlint.config.cjs, workflows.

Ограничения, принимаемые явно

  • Freeze релиза не поддерживается: нельзя заморозить кандидат и параллельно мержить в develop.
  • Hotfix — обычная ветка fix/* от develop с последующим релизом. Если develop содержит незаконченную работу, быстрого фикса нет. Escape hatch (release от main + cherry-pick) допустим как разовое исключение ценой нарушения инварианта и последующего back-merge.

Acceptance Criteria

  • .ai/conventions/git.md, README.md и .ai/conventions/engineering-workflow.md описывают модель выше; back-merge и hotfix от main удалены
  • Инвариант и команда его проверки записаны в документах
  • Gitea repo settings во всех пяти: allow_merge_commits: false, allow_rebase_explicit: false, default_merge_style: squash, default_update_style: rebase, default_delete_branch_after_merge: true
  • Branch protection main/develop выровнена между пятью репозиториями: enable_push: false, enable_force_push: false, block_on_outdated_branch: true, корректные status_check_contexts
  • Tag protection v* подтверждена во всех пяти
  • Инвариант проверен после применения во всех пяти

Связанные Issue

  • WealthLedger/backend
  • WealthLedger/frontend
  • WealthLedger/docs
  • WealthLedger/specs

Порядок: документы в каждом repo независимы, Gitea-настройки применяются после merge документов.

## Контекст Текущий процесс (README.md:154-211) описывает release-ветку от `develop`, ff-only merge в `main` и обратную синхронизацию PR `main → develop`. Back-merge существует только ради коммита `chore(release): X.Y.Z`, который создаётся на release-ветке и потому отсутствует в `develop`. Он оставляет merge-коммит в `develop` при каждом релизе. Gitea при этом не принуждает линейность: во всех пяти репозиториях `allow_merge_commits: true` и `default_merge_style: merge`. В истории `main` присутствуют merge-коммиты (`d2d1092`, `3321d9d`, `ed8221a` в root; `774e58e` в backend). Проверено на момент создания Issue: `origin/main` является предком `origin/develop` во всех пяти репозиториях. Переход возможен без переписывания истории. ## Решение Модель: ``` feature/* --squash|rebase-merge--> develop --ff-only--> main --> tag vX.Y.Z ``` **Инвариант: `origin/main` всегда предок `origin/develop`.** Релиз: 1. `git fetch origin --tags`; ветка `release/X.Y.Z` от свежего `develop` 2. `npm run release:preview`, затем `npm run release:prepare` 3. PR `release/X.Y.Z → develop`, title `chore(release): X.Y.Z`, ff-only merge 4. PR `develop → main`, тот же title, ff-only merge 5. `git tag -a vX.Y.Z <main-sha> -m "Release X.Y.Z"`; `git push origin refs/tags/vX.Y.Z` Убирается: back-merge `main → develop`, cherry-pick, rebase `develop`, `release/hotfix-*` от `main`. Не меняется: `.release-it.json` (`requireBranch: "release/*"` работает без правок), `commitlint.config.cjs`, workflows. ## Ограничения, принимаемые явно - Freeze релиза не поддерживается: нельзя заморозить кандидат и параллельно мержить в `develop`. - Hotfix — обычная ветка `fix/*` от `develop` с последующим релизом. Если `develop` содержит незаконченную работу, быстрого фикса нет. Escape hatch (release от `main` + cherry-pick) допустим как разовое исключение ценой нарушения инварианта и последующего back-merge. ## Acceptance Criteria - [ ] `.ai/conventions/git.md`, `README.md` и `.ai/conventions/engineering-workflow.md` описывают модель выше; back-merge и hotfix от `main` удалены - [ ] Инвариант и команда его проверки записаны в документах - [ ] Gitea repo settings во всех пяти: `allow_merge_commits: false`, `allow_rebase_explicit: false`, `default_merge_style: squash`, `default_update_style: rebase`, `default_delete_branch_after_merge: true` - [ ] Branch protection `main`/`develop` выровнена между пятью репозиториями: `enable_push: false`, `enable_force_push: false`, `block_on_outdated_branch: true`, корректные `status_check_contexts` - [ ] Tag protection `v*` подтверждена во всех пяти - [ ] Инвариант проверен после применения во всех пяти ## Связанные Issue - WealthLedger/backend - WealthLedger/frontend - WealthLedger/docs - WealthLedger/specs Порядок: документы в каждом repo независимы, Gitea-настройки применяются после merge документов.
Author
Owner

Связанные Issue созданы:

Baseline, снятый перед работой:

Инвариант origin/main предок origin/develop — выполняется во всех пяти репозиториях.

Merge-настройки идентичны во всех пяти и разрешают merge-коммиты:
allow_merge_commits=true, allow_squash_merge=true, allow_fast_forward_only_merge=true, allow_rebase=true, allow_rebase_explicit=true, default_merge_style=merge, default_update_style=merge, default_delete_branch_after_merge=false.

Branch protection существует во всех пяти (rule_name: {main,develop}), но расходится:

repo push force_push outdated contexts
main false false true Conventional commits / commits (pull_request)
frontend false true false Frontend verify / {commits,security,verify} (pull_request)
backend true (wl: ksv741) false true Backend verify / {commits,security,verify} (pull_request)
docs false false true Docs verify / verify, Docs security / security, Conventional commits / commits
specs false false true Specs verify / verify, Specs security / security, Conventional commits / commits

Tag protection v* с whitelist ksv741 присутствует во всех пяти. Контексты уже корректны везде, дополнительный проход за ними не нужен.

Выравнивание frontend (force_push, outdated) и backend (прямой push) входит в scope этой Issue.

Связанные Issue созданы: - WealthLedger/backend#111 - WealthLedger/frontend#91 - WealthLedger/docs#49 - WealthLedger/specs#48 Baseline, снятый перед работой: Инвариант `origin/main` предок `origin/develop` — выполняется во всех пяти репозиториях. Merge-настройки идентичны во всех пяти и разрешают merge-коммиты: `allow_merge_commits=true`, `allow_squash_merge=true`, `allow_fast_forward_only_merge=true`, `allow_rebase=true`, `allow_rebase_explicit=true`, `default_merge_style=merge`, `default_update_style=merge`, `default_delete_branch_after_merge=false`. Branch protection существует во всех пяти (`rule_name: {main,develop}`), но расходится: | repo | push | force_push | outdated | contexts | | --- | --- | --- | --- | --- | | main | false | false | true | `Conventional commits / commits (pull_request)` | | frontend | false | **true** | **false** | `Frontend verify / {commits,security,verify} (pull_request)` | | backend | **true** (wl: ksv741) | false | true | `Backend verify / {commits,security,verify} (pull_request)` | | docs | false | false | true | `Docs verify / verify`, `Docs security / security`, `Conventional commits / commits` | | specs | false | false | true | `Specs verify / verify`, `Specs security / security`, `Conventional commits / commits` | Tag protection `v*` с whitelist `ksv741` присутствует во всех пяти. Контексты уже корректны везде, дополнительный проход за ними не нужен. Выравнивание frontend (force_push, outdated) и backend (прямой push) входит в scope этой Issue.
Author
Owner

Выполнено. Все пять PR слиты squash: main#35, backend#112, frontend#92, docs#50, specs#49.

Gitea после применения

Repo settings во всех пяти:
allow_merge_commits=false, allow_rebase_explicit=false, allow_rebase=true, allow_squash_merge=true, allow_fast_forward_only_merge=true, default_merge_style=squash, default_update_style=rebase, default_delete_branch_after_merge=true.

Branch protection {main,develop} во всех пяти выровнена:
enable_push=false, enable_push_whitelist=false, enable_force_push=false, enable_force_push_allowlist=false, enable_status_check=true, block_on_outdated_branch=true, block_admin_merge_override=true.

Устранённые расхождения baseline: frontend разрешал force-push и не блокировал устаревшую ветку; backend разрешал прямой push ksv741.

Tag protection v* с whitelist ksv741 подтверждена во всех пяти. Контексты обязательных проверок оставлены как были — они уже соответствовали workflows каждого repo.

Verification

Инвариант git merge-base --is-ancestor origin/main origin/develop — ok во всех пяти после merge.

origin/develop HEAD каждого repo — одиночный squash-коммит без merge-записи:

  • main 0bdc409
  • frontend eefdde2
  • backend 4f485ab
  • docs 11f819e
  • specs 06d08e2

Полная сверка настроек по API: пять из пяти ALL OK по 14 проверкам (merge styles, protection, tag protection).

CI на финальных ревизиях: commits в root; verify, security, commits в backend/frontend; verify, security, commits в docs/specs — все success.

Рабочие ветки удалены на сервере (delete_branch=true) и локально.

Не входило в scope

.release-it.json и commitlint.config.cjs не менялись — requireBranch: "release/*" и ignore-правило chore(release): X.Y.Z работают с новым процессом без правок. Релизный PR теперь идёт в develop, что покрывается существующей веткой-ограничением.

Первый релиз по новой схеме подтвердит, что ветка release/X.Y.Z → develop проходит ff-only merge: develop не должен двигаться, пока PR открыт.

Выполнено. Все пять PR слиты squash: main#35, backend#112, frontend#92, docs#50, specs#49. ## Gitea после применения Repo settings во всех пяти: `allow_merge_commits=false`, `allow_rebase_explicit=false`, `allow_rebase=true`, `allow_squash_merge=true`, `allow_fast_forward_only_merge=true`, `default_merge_style=squash`, `default_update_style=rebase`, `default_delete_branch_after_merge=true`. Branch protection `{main,develop}` во всех пяти выровнена: `enable_push=false`, `enable_push_whitelist=false`, `enable_force_push=false`, `enable_force_push_allowlist=false`, `enable_status_check=true`, `block_on_outdated_branch=true`, `block_admin_merge_override=true`. Устранённые расхождения baseline: frontend разрешал force-push и не блокировал устаревшую ветку; backend разрешал прямой push `ksv741`. Tag protection `v*` с whitelist `ksv741` подтверждена во всех пяти. Контексты обязательных проверок оставлены как были — они уже соответствовали workflows каждого repo. ## Verification Инвариант `git merge-base --is-ancestor origin/main origin/develop` — `ok` во всех пяти после merge. `origin/develop` HEAD каждого repo — одиночный squash-коммит без merge-записи: - main `0bdc409` - frontend `eefdde2` - backend `4f485ab` - docs `11f819e` - specs `06d08e2` Полная сверка настроек по API: пять из пяти `ALL OK` по 14 проверкам (merge styles, protection, tag protection). CI на финальных ревизиях: `commits` в root; `verify`, `security`, `commits` в backend/frontend; `verify`, `security`, `commits` в docs/specs — все `success`. Рабочие ветки удалены на сервере (`delete_branch=true`) и локально. ## Не входило в scope `.release-it.json` и `commitlint.config.cjs` не менялись — `requireBranch: "release/*"` и ignore-правило `chore(release): X.Y.Z` работают с новым процессом без правок. Релизный PR теперь идёт в `develop`, что покрывается существующей веткой-ограничением. Первый релиз по новой схеме подтвердит, что ветка `release/X.Y.Z → develop` проходит ff-only merge: `develop` не должен двигаться, пока PR открыт.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: WealthLedger/main#34