强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Git 服务器搭建完全指南 / 第 7 章 - 多项目管理

第 7 章 - 多项目管理

随着团队和项目数量增长,如何设计合理的组织架构、团队结构和权限继承体系变得至关重要。

7.1 组织架构设计

7.1.1 常见组织模型

模型 适用场景 示例
按部门划分 传统企业 前端部、后端部、运维部
按产品划分 产品驱动型 电商平台、内部工具、数据分析
按服务划分 微服务架构 用户服务、订单服务、支付服务
混合模型 中大型企业 部门 + 产品线交叉

7.1.2 Gitea/Forgejo 组织设计

Organizations (组织)
├── platform (平台部)
│   ├── Teams
│   │   ├── frontend (前端团队)
│   │   ├── backend (后端团队)
│   │   └── devops (运维团队)
│   └── Repositories
│       ├── web-app (前端 + 后端)
│       ├── api-gateway (后端 + 运维)
│       └── shared-lib (前端 + 后端)
│
├── product (产品部)
│   ├── Teams
│   │   ├── mobile (移动端)
│   │   └── data (数据团队)
│   └── Repositories
│       ├── ios-app
│       ├── android-app
│       └── data-pipeline
│
└── infra (基础设施)
    ├── Teams
    │   └── sre
    └── Repositories
        ├── terraform
        ├── ansible
        └── monitoring

7.1.3 通过 API 创建组织和团队

GITEA_URL="https://git.example.com"
TOKEN="your_admin_token"

# 创建组织
create_org() {
  curl -s -X POST -H "Authorization: token $TOKEN" \
    -H "Content-Type: application/json" \
    "$GITEA_URL/api/v1/orgs" \
    -d "{
      \"username\": \"$1\",
      \"full_name\": \"$2\",
      \"description\": \"$3\",
      \"visibility\": \"limited\"
    }" | jq '.id'
}

ORG_ID=$(create_org "platform" "平台部" "平台技术团队")

# 创建团队
create_team() {
  curl -s -X POST -H "Authorization: token $TOKEN" \
    -H "Content-Type: application/json" \
    "$GITEA_URL/api/v1/orgs/$1/teams" \
    -d "{
      \"name\": \"$2\",
      \"description\": \"$3\",
      \"permission\": \"$4\",
      \"units\": [\"repo.code\", \"repo.issues\", \"repo.pulls\", \"repo.releases\"]
    }"
}

create_team "platform" "frontend" "前端团队" "write"
create_team "platform" "backend" "后端团队" "write"
create_team "platform" "devops" "运维团队" "admin"

7.1.4 GitLab Group 嵌套结构

GitLab 支持 Group 嵌套,适合更复杂的组织架构:

Group: company (顶层)
├── SubGroup: engineering
│   ├── SubGroup: frontend
│   │   ├── Project: design-system
│   │   └── Project: web-app
│   ├── SubGroup: backend
│   │   ├── Project: api-server
│   │   └── Project: auth-service
│   └── SubGroup: platform
│       ├── Project: infrastructure
│       └── Project: monitoring
├── SubGroup: product
│   ├── Project: mobile-app
│   └── Project: data-analytics
└── SubGroup: shared
    ├── Project: docs
    └── Project: coding-standards
# 创建顶层 Group
curl -s -X POST -H "PRIVATE-TOKEN: $TOKEN" \
  "$GITLAB_URL/api/v4/groups" \
  -d '{
    "name": "Company",
    "path": "company",
    "visibility": "internal"
  }'

# 创建子 Group
curl -s -X POST -H "PRIVATE-TOKEN: $TOKEN" \
  "$GITLAB_URL/api/v4/groups" \
  -d '{
    "name": "Engineering",
    "path": "engineering",
    "parent_id": TOP_LEVEL_GROUP_ID,
    "visibility": "internal"
  }'

# 在子 Group 下创建项目
curl -s -X POST -H "PRIVATE-TOKEN: $TOKEN" \
  "$GITLAB_URL/api/v4/projects" \
  -d '{
    "name": "Web App",
    "path": "web-app",
    "namespace_id": ENGINEERING_GROUP_ID,
    "visibility": "internal"
  }'

7.2 权限继承体系

7.2.1 Gitea 权限继承

Organization 权限
    ├── Owner  → 组织 Owner,完全控制
    ├── Member → 组织成员,自动获得组织仓库的读取权限
    │
    └── Team 权限(覆盖或补充组织权限)
        ├── Admin  → 团队管理的仓库完全控制
        ├── Write  → 读写
        ├── Read   → 只读
        └── 自定义 → 精细权限

规则:用户对仓库的有效权限 = max(组织成员权限, 团队权限)

7.2.2 GitLab 权限继承

Group (Owner: 50)
├── 成员继承规则
│   ├── Group 级别成员 → 自动继承到所有子 Group 和 Project
│   ├── SubGroup 级别成员 → 继承到其下所有子 Group 和 Project
│   └── Project 级别成员 → 仅限该项目
│
├── 权限取最高值
│   User 在 Group=Reporter, 在 Project=Developer → 有效权限 = Developer
│
└── 最大角色传播
    Group Owner → 所有子 Group 和 Project 的 Owner

继承示例

# 在 Group 级别添加成员,自动继承到所有子项目
curl -s -X POST -H "PRIVATE-TOKEN: $TOKEN" \
  "$GITLAB_URL/api/v4/groups/GROUP_ID/members" \
  -d '{
    "user_id": 123,
    "access_level": 30
  }'
# 用户 123 自动获得该 Group 下所有项目 Developer 权限

7.2.3 权限矩阵设计

角色 创建仓库 推送代码 合并 MR 管理 Issue 管理项目设置 管理成员
外部贡献者 Fork 推送 评论
访客 (Guest)
报告者 (Reporter)
开发者 (Developer)
维护者 (Maintainer)
管理员 (Owner)

7.3 仓库模板管理

7.3.1 Gitea 组织模板仓库

# 创建模板仓库(在 Web 界面中设置为 Template)
curl -s -X POST -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  "$GITEA_URL/api/v1/orgs/platform/repos" \
  -d '{
    "name": "template-node-app",
    "description": "Node.js 应用模板仓库",
    "template": false,
    "auto_init": true,
    "default_branch": "main"
  }'

在模板仓库中预置:

template-node-app/
├── .github/
│   └── ISSUE_TEMPLATE/
│       ├── bug_report.md
│       └── feature_request.md
├── .gitea/
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── .editorconfig
├── .eslintrc.js
├── Dockerfile
├── docker-compose.yml
├── README.md
├── LICENSE
├── package.json
└── src/
    └── index.js

7.3.2 GitLab 项目模板

GitLab 支持 Group 级别的项目模板:

# 设置 Group 项目模板
# Web 界面: Group → Settings → General → Templates → Select a template group

# 或通过 API
curl -s -X PUT -H "PRIVATE-TOKEN: $TOKEN" \
  "$GITLAB_URL/api/v4/groups/GROUP_ID" \
  -d '{
    "project_creation_level": "developer",
    "subgroup_creation_level": "maintainer",
    "default_branch_protection": 2
  }'

7.4 分支保护策略

7.4.1 Gitea 分支保护

# 通过 API 设置分支保护
curl -s -X POST -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  "$GITEA_URL/api/v1/repos/owner/repo/branches/main/protection" \
  -d '{
    "enable_push": true,
    "enable_push_whitelist": true,
    "push_whitelist_usernames": ["alice", "bob"],
    "enable_merge_whitelist": true,
    "merge_whitelist_usernames": ["alice"],
    "enable_status_check": true,
    "status_check_contexts": ["ci/build", "ci/test"],
    "required_approvals": 2,
    "enable_approvals_whitelist": true,
    "approvals_whitelist_usernames": ["alice", "bob"]
  }'

7.4.2 GitLab 分支保护规则

# 保护 main 分支
curl -s -X POST -H "PRIVATE-TOKEN: $TOKEN" \
  -H "Content-Type: application/json" \
  "$GITLAB_URL/api/v4/projects/PROJECT_ID/protected_branches" \
  -d '{
    "name": "main",
    "push_access_level": 40,
    "merge_access_level": 30,
    "unprotect_access_level": 40,
    "allow_force_push": false,
    "code_owner_approval_required": true
  }'

# 保护 release/* 通配符
curl -s -X POST -H "PRIVATE-TOKEN: $TOKEN" \
  "$GITLAB_URL/api/v4/projects/PROJECT_ID/protected_branches" \
  -d '{
    "name": "release/*",
    "push_access_level": 40,
    "merge_access_level": 40
  }'

7.4.3 分支保护矩阵

分支模式 保护级别 推送权限 合并权限 适用场景
main 严格 Maintainer Developer(需 Review) 生产代码
dev 中等 Developer Developer 开发集成
feature/* 宽松 Developer Developer 功能开发
release/* 严格 Maintainer Maintainer 发布管理
hotfix/* 中等 Maintainer Maintainer 紧急修复

7.5 标签和里程碑管理

7.5.1 标签(Labels)标准化

# 批量创建标准标签
GITEA_URL="https://git.example.com"
TOKEN="your_token"
REPO="owner/repo"

labels=(
  '{"name":"bug","color":"#d73a4a","description":"Bug 报告"}'
  '{"name":"feature","color":"#0075ca","description":"新功能"}'
  '{"name":"enhancement","color":"#a2eeef","description":"改进"}'
  '{"name":"documentation","color":"#0075ca","description":"文档"}'
  '{"name":"good first issue","color":"#7057ff","description":"适合新手"}'
  '{"name":"priority:high","color":"#b60205","description":"高优先级"}'
  '{"name":"priority:medium","color":"#fbca04","description":"中优先级"}'
  '{"name":"priority:low","color":"#0e8a16","description":"低优先级"}'
  '{"name":"status:blocked","color":"#e4e669","description":"被阻塞"}'
  '{"name":"status:in-progress","color":"#c2e0c6","description":"进行中"}'
  '{"name":"status:review","color":"#bfdadc","description":"待审查"}'
  '{"name":"team:frontend","color":"#ededed","description":"前端团队"}'
  '{"name":"team:backend","color":"#ededed","description":"后端团队"}'
)

for label_json in "${labels[@]}"; do
  curl -s -X POST -H "Authorization: token $TOKEN" \
    -H "Content-Type: application/json" \
    "$GITEA_URL/api/v1/repos/$REPO/labels" \
    -d "$label_json" | jq '.name'
done

7.5.2 里程碑管理

# 创建里程碑
curl -s -X POST -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  "$GITEA_URL/api/v1/repos/$REPO/milestones" \
  -d '{
    "title": "v2.0",
    "description": "2.0 版本发布",
    "due_on": "2026-08-01T00:00:00+08:00"
  }'

7.6 批量管理脚本

7.6.1 仓库批量创建

#!/bin/bash
# batch-create-repos.sh

GITEA_URL="https://git.example.com"
TOKEN="your_token"
ORG="platform"

repos=(
  '{"name":"web-app","description":"Web 前端应用","auto_init":true,"default_branch":"main"}'
  '{"name":"api-server","description":"API 服务端","auto_init":true,"default_branch":"main"}'
  '{"name":"shared-lib","description":"共享库","auto_init":true,"default_branch":"main"}'
  '{"name":"design-docs","description":"设计文档","auto_init":true,"default_branch":"main"}'
)

for repo_json in "${repos[@]}"; do
  echo "Creating repo..."
  curl -s -X POST -H "Authorization: token $TOKEN" \
    -H "Content-Type: application/json" \
    "$GITEA_URL/api/v1/orgs/$ORG/repos" \
    -d "$repo_json" | jq '{name: .full_name, url: .clone_url}'
done

7.6.2 权限审计脚本

#!/bin/bash
# audit-permissions.sh

GITEA_URL="https://git.example.com"
TOKEN="your_admin_token"

echo "=== 仓库权限审计 ==="
echo ""

# 获取所有组织
orgs=$(curl -s -H "Authorization: token $TOKEN" \
  "$GITEA_URL/api/v1/orgs?limit=50" | jq -r '.[].username')

for org in $orgs; do
  echo "--- Organization: $org ---"
  
  # 获取组织团队
  teams=$(curl -s -H "Authorization: token $TOKEN" \
    "$GITEA_URL/api/v1/orgs/$org/teams" | jq -r '.[].name')
  
  for team in $teams; do
    # 获取团队成员
    members=$(curl -s -H "Authorization: token $TOKEN" \
      "$GITEA_URL/api/v1/orgs/$org/teams/$team/members" | jq -r '.[].login')
    
    # 获取团队权限
    permission=$(curl -s -H "Authorization: token $TOKEN" \
      "$GITEA_URL/api/v1/orgs/$org/teams/$team" | jq -r '.permission')
    
    printf "  Team: %-20s Permission: %-10s Members: %s\n" \
      "$team" "$permission" "$(echo $members | tr '\n' ', ')"
  done
  
  echo ""
done

7.7 扩展阅读


本章小结

学到了什么 关键要点
组织模型 按部门/产品/服务划分,选择适合团队的模型
权限继承 上级权限自动继承到下级,有效权限取最高值
分支保护 main/develop 严格保护,feature 宽松
模板管理 使用模板仓库统一项目结构和配置
批量管理 API + 脚本实现批量创建和审计

下一章:第 8 章 - 服务端钩子 — 利用 Git 钩子实现推送检查、自动部署和通知。