# Gitea FF-only 是仓库级配置，不是分支保护字段

## 场景

讨论把 `develop → staging → production` 从 plain merge 改为 fast-forward only，本能反应是去分支保护里找开关（类似 GitHub 的 `require_linear_history`）。

## 不直观的点

Gitea 的分支保护 API（`/api/v1/repos/{owner}/{repo}/branch_protections/{branch}`）**没有** merge style 字段，也没有 `require_linear_history`。FF-only 这件事在 Gitea 里是**仓库级**配置：

```
GET /api/v1/repos/{owner}/{repo}
→ allow_merge_commits / allow_rebase / allow_rebase_explicit
  / allow_squash_merge / allow_fast_forward_only_merge / default_merge_style
```

含义：Gitea 控制的是"PR 合并按钮下拉里能选哪些 style"，而不是"目标分支必须用某 style"。**没法按目标分支强制不同 style**。

## 我们的应对

收敛仓库级 styles：只留 `squash`（develop 用，default）+ `fast-forward-only`（staging/production 用），把 `merge` / `rebase` / `rebase-merge` 全关掉。这样合并下拉只剩 2 个选项，靠 reviewer 在 staging/production PR 上选 FF-only——能防呆但不是硬强制。

```bash
curl -X PATCH -H "Authorization: token $GITEA_API_TOKEN" \
  http://43.130.59.228/api/v1/repos/FFAIWorkspace/workspace \
  -d '{"allow_merge_commits":false,"allow_rebase":false,"allow_rebase_explicit":false,"allow_squash_merge":true,"allow_fast_forward_only_merge":true,"default_merge_style":"squash"}'
```

## 后续可加的硬强制

如果想真正强制 staging/production 上不出现 merge commit，得加一个 Gitea Actions workflow，在 `push: [staging, production]` 时校验 `git rev-list --merges <prev>..<new>` 为空。当前没做。

## Takeaways

- Gitea ≠ GitHub，找配置先 `GET /repos/{owner}/{repo}` 看整体字段，不要先去分支保护里翻
- "按目标分支强制不同 merge style" 在 Gitea 里做不到原生，得靠仓库级收敛 + 约定 + 可选 CI 校验
- 默认 merge style 影响所有 PR 的默认选项，不影响"是否允许"——allow 才是允许开关
