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

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严格MaintainerDeveloper(需 Review)生产代码
dev中等DeveloperDeveloper开发集成
feature/*宽松DeveloperDeveloper功能开发
release/*严格MaintainerMaintainer发布管理
hotfix/*中等MaintainerMaintainer紧急修复

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 钩子实现推送检查、自动部署和通知。