---
module: platform.git-workflow
title: Git & Deploy Workflow
tab: Overview
order: 50
audience: dev
---

> **DRAFT · internal** (2026-07-01). Written after violating this repeatedly in one session.

## The one rule (service repos: `hiveops-*`)
- **Commit DIRECTLY to `develop`. No feature branch for normal work. No PR into develop.**
  `git checkout develop` in the sub-project → pull → edit → commit with `#NN` → push develop.
- **NEVER work on `main`.** (Working on stale main once caused a full duplication of work that
  already existed on develop.)
- **Exception — ONLY when Johannes says "hotfix on main":** `hotfix/*` branch off main → PR to
  `main` → Johannes approves in the Gitea UI (SOC2) → he explicitly says "deploy". That is the
  only time branches, PRs, or main are involved.

## Enforced by a hook
`.claude/hooks/block-commit-on-main.py` blocks `git commit` while HEAD is `main` — because a
written rule alone did not reliably stop me. It **exempts deployment/config/docs repos** that live
on main by design (openmetal / hiveiq-ops / hiveops-devops / hiveops-docs / hiveops-release /
hiveiq-claude) and the monorepo root.

## Deployment/config repos
`hiveiq-openmetal-dev` (bcos.dev config) now uses **`develop`** too (as of 2026-07-01). Other
config repos historically live on `main` — confirm per repo.

## Gates that always stay manual
- **PR approval** (develop→main) in the Gitea UI — SOC2 separation of duties; never self-approve.
- **Prod deploy go** — separate from merge. Merge ≠ deploy. Deploy to the **standby** blue/green
  slot, verify, then switch nginx **and** internal callers together.
- **Prod DB writes / SSH to prod hosts** — deliberate, prompted.

## Trackers
`Refs #N` in commits/PRs — **never `Fixes #N`/`Closes #N`** (auto-close bypasses the Verify Fix →
tester gate). Issue-first: every change traces to a Gitea issue.
