git-workflow

Git-гигиена и релизная дисциплина — Conventional Commits (таблица типов, BREAKING CHANGE), semver-правила бампа, поимённые коммиты и запрет `git add .`/`git add -A` при параллельных сессиях, ловушка s

SKILL.md

GitHub

Навык: Git-workflow и релизы

Ключевой принцип: история — публичный документ. Каждый коммит читают ревьюеры, git bisect и генератор changelog. Состояние репозитория проверяй сам (git status, git diff) — не верь отчётам «всё чисто» на слово.

1. Conventional Commits

Формат: тип(scope): суть в повелительном наклонении — до ~72 символов, без точки в конце.

Тип Когда Semver
feat Новая функциональность для пользователя minor
fix Исправление бага patch
docs Только документация patch/—
refactor Перестройка кода без изменения поведения patch
perf Ускорение без изменения поведения patch
test Добавление/правка тестов —
chore Обслуживание: зависимости, конфиги, скрипты —
ci / build Пайплайны / система сборки —

BREAKING CHANGE: несовместимое изменение → ! после типа (feat!:) и/или футер BREAKING CHANGE: описание миграции. Это единственное, что бампает major — независимо от типа.

2. Semver: что бампает версию

  • major (X.0.0) — любой BREAKING CHANGE (API, схема, формат конфига).
  • minor (x.Y.0) — хотя бы один feat без breaking.
  • patch (x.y.Z) — только fix/refactor/perf/docs.
  • Версия релиза = максимум по всем коммитам с прошлого тега. Тег vX.Y.Z обязан совпадать с версиями в манифестах (package.json, plugin.json и т.п.) — иначе релиз невоспроизводим.

3. Поимённые коммиты — почему git add . опасен

Параллельные сессии (multi-clauding) слепы друг к другу: в одном рабочем каталоге может лежать чужой незакоммиченный WIP. git add . / git add -A захватит его в твой коммит — молча.

git status --porcelain            # сам посмотри, что реально изменено
git diff -- src/api/users.ts      # проверь содержимое перед add
git add src/api/users.ts src/api/users.test.ts   # ТОЛЬКО по именам
git commit -m "fix(api): не терять 404 при пустом userId"
git status                        # после коммита: чужой WIP остался нетронут

Незнакомые/несвязанные изменения в git status — стоп и спроси владельца, не включай их.

4. Ловушка squash-merge долгоживущей ветки

После squash-PR в main base получает один squash-коммит, не связанный с историей ветки → следующий PR той же ветки даёт ложные конфликты («те же файлы расходятся»).

Диагностика ПЕРЕД пушем ветки, у которой уже был squash-PR:

git fetch
git merge-base --is-ancestor origin/main HEAD && echo ok || echo "base ушёл вперёд"

Если base ушёл вперёд — feat почти всегда надмножество. Подтверди: git diff origin/main <squash-точка> пуст → разрешай:

git merge -s ours origin/main   # делает base предком, сохраняя дерево ветки без потерь

Анализируй заранее, не жди сообщения GitHub о конфликте.

5. Worktree для параллельной работы

Параллельная/фоновая задача в том же репо → отдельный каталог и ветка: git worktree add <os-worktree-root>/<repo>-<slug>-<stamp> -b feat/<slug> HEAD. Каждое окно получает свой каталог — коммиты не пересекаются. После вливания: git worktree remove --force … && git worktree prune. Канон — скилл worktree-workflow.

6. Changelog (Keep a Changelog)

CHANGELOG.md: секция [Unreleased] сверху, релизы ## [X.Y.Z] - YYYY-MM-DD; рубрики Added (feat) / Fixed (fix) / Changed (refactor, perf, поведенческие правки) / Breaking (или Changed с пометкой) / Deprecated / Removed / Security. Источник — git log <prev-tag>..HEAD, но пиши для человека: что изменилось для пользователя, а не пересказ коммитов.

7. Безопасность

  • Force-push запрещён. Rebase опубликованных веток, push --force, удаление чужих веток — только с явного подтверждения владельца (и предпочитай --force-with-lease).
  • push / publish / release — только с явного подтверждения. Локальные коммиты и теги готовь свободно; всё, что уходит наружу — стоп и спроси.
  • Неоднозначное односложное «ок»/«go»/«давай» — не авторизация необратимого действия. Переспроси, назвав действие явно: «пушу тег v2.0.0 и публикую релиз — подтверди».