前言
前面几篇文章主要在讲Git本身:
- 怎么配置Git和Gitea
- 怎么提交代码
- 多人协作怎么走Pull Request
- 遇到冲突怎么处理
到这里,基本已经能做到:
clone -> 开发 -> commit -> push -> Pull Request -> merge但真正做项目协作时,只会这些还不够。
很多人会clone、会push、会创建Pull Request,但是看到仓库里的这些功能就不知道是干什么的:
Issue(工作项)Milestone(里程碑)Label(标签)Project(项目)Wiki(项目文档)Release(版本发布)
这些功能看起来像是附加功能,实际上它们才是项目协作里很重要的一部分。
Git解决的是“代码怎么管理”,而Gitea这些功能解决的是:
事情怎么记录任务怎么分配进度怎么跟踪版本怎么发布文档放在哪里这篇就从这些常见功能开始,讲一下Gitea里一个项目到底应该怎么协作。
Issue(工作项)
先讲Issue,因为这是最重要的。
很多人会把Issue翻译成“问题”,但这样容易理解窄了。
更准确地说:
Issue = 一条工作记录它可以是很多东西:
- Bug
- 功能需求
- 优化建议
- 待办任务
- 文档补充
- 讨论事项
比如:
修复登录失败问题增加深色模式优化首页加载速度补充部署文档调整用户权限逻辑这些都可以创建成Issue。
如果没有Issue,团队协作很容易变成这样:
微信群里说了一句过几天没人记得谁负责也不知道做没做完也不知道有了Issue以后,每一件事都有一个记录,可以看到是谁提的、谁负责、现在做到哪一步、最后怎么解决的。
创建Issue(工作项)
在Gitea仓库页面里,一般可以进入Issues页面,然后点击New Issue创建。

创建Issue时,主要看这几项:
- 标题
- 描述
- 指派人
- 标签
- 里程碑
标题要简短明确,不要只写“有问题”“修一下”“报错了”。
比如下面这种标题就不太好:
登录有问题可以写得更具体一点:
修复密码错误时登录页面没有提示的问题描述里可以写清楚:
- 现在是什么现象
- 期望应该是什么样
- 怎么复现
- 有没有截图或日志
- 影响范围大不大
Bug类Issue可以这样写:
### 问题描述
用户输入错误密码后,页面没有显示错误提示。
### 复现步骤
1. 打开登录页面2. 输入已存在账号3. 输入错误密码4. 点击登录
### 期望结果
页面提示“账号或密码错误”。
### 实际结果
页面没有任何提示。功能需求可以这样写:
### 需求说明
希望增加考试成绩导出功能,管理员可以导出某场考试的成绩表。
### 需要包含
- 学生姓名- 学号- 分数- 提交时间
### 备注
第一版可以先支持导出 CSV。写清楚Issue,其实就是减少后面沟通成本。
Issue(工作项)的生命周期
一个Issue通常会经历这样的过程:
Open↓分配负责人↓处理中↓提交 Pull Request↓Review↓合并↓关闭刚创建出来的Issue一般是Open状态,表示这个事情还没有完成。
处理完成后,可以手动关闭,也可以在Pull Request合并时自动关闭。
比如在PR描述里写:
Closes #12这个PR合并后,编号为#12的Issue就会自动关闭。
如果只是关联Issue,不想自动关闭,可以写:
Related to #12这样别人看PR时,就能知道这次代码修改和哪个Issue有关。
Label(标签)
Label就是标签,用来给Issue或Pull Request分类。
常见标签有:
bugenhancementdocumentationquestionhelp wanted大概可以这样理解:
bug:程序问题enhancement:功能增强或优化documentation:文档相关question:问题或讨论help wanted:需要别人帮忙
标签的作用不是装饰,而是方便筛选。
比如你只想看所有Bug,就可以筛选bug标签;只想看文档任务,就筛选documentation。
项目大一点后,如果所有Issue都没有标签,列表会很乱。
一个比较简单的标签体系可以这样:
bugfeaturedocsuibackendpriority-highpriority-low刚开始不用设计得太复杂,够用就行。标签太多没人维护,最后也会变成摆设。
Assignee(负责人)
Assignee就是负责人。
一个Issue创建出来以后,如果没人负责,它很容易被放在那里没人处理。
比较好的做法是:
Issue↓指定给张三↓张三负责跟进被指派的人不一定要一个人完成所有代码,但至少要负责推进这件事。
比如:
- 确认需求
- 写代码
- 找人Review
- 更新进度
- 最后关闭Issue
如果一个Issue暂时没人处理,可以先不指派。但只要进入开发阶段,最好明确负责人。
Milestone(里程碑)
Milestone是里程碑。
这个功能很多人不太会用,因为它不像Issue那么直观。
可以简单理解成:
Milestone = 一个版本或阶段的目标集合比如:
v1.0v1.1v2.0一个版本通常不只包含一个任务,而是包含多个Issue。
例如v1.1这个里程碑里可能有:
修复登录失败问题增加深色模式优化首页加载速度补充部署文档这些Issue都完成后,v1.1这个里程碑才算完成。
所以Milestone适合回答这个问题:
这个版本还有哪些事情没做完?如果只是个人小项目,不用Milestone也能写。但只要项目开始有版本计划,比如v1.0、v1.1,Milestone就很有用了。

Project(项目看板)
Project可以理解成项目看板,类似常见的Kanban。
最简单的看板一般有三列:
TODO↓Doing↓Done也可以写成中文:
待办↓进行中↓已完成Issue可以放到看板里,然后随着进度移动。
比如一个任务刚提出来时,放在TODO;有人开始处理后,移动到Doing;完成并合并后,移动到Done。
Project适合回答这个问题:
现在大家都在做什么?哪些任务还没开始?哪些任务已经完成?如果只看Issue列表,有时不太直观。Project看板能让进度一眼看出来。

刚开始可以只建一个简单看板:
TODODoingDone不要一开始就搞太多列,比如“需求池”“待评审”“开发中”“测试中”“待发布”“已发布”。流程太复杂,反而没人愿意维护。
Pull Request(合并请求)
Pull Request前面已经单独讲过,这里简单串一下。
在Gitea项目协作里,Pull Request通常不是孤立存在的。
更完整的流程应该是:
Issue↓开发↓Pull Request↓Review↓Merge↓关闭 Issue也就是说,PR最好能对应某个Issue。
比如有一个Issue:
#12 添加考试成绩导出功能开发者创建PR时,可以在描述里写:
Closes #12这样PR合并后,Issue会自动关闭,整个任务链路就完整了。
如果一个PR没有对应Issue,也不是绝对不行。比如很小的文案修改、临时修复,可以直接PR。但对于稍微复杂一点的功能,先有Issue再有PR会更清楚。
Wiki(项目文档)
Wiki适合放项目文档。
很多人会把所有东西都写进README.md,刚开始没问题,但项目复杂后,README会越来越长。
这时可以把一些长期文档放到Wiki里,比如:
- 部署文档
- 开发规范
- 接口文档
- 数据库说明
- 常见问题
- 环境变量说明
README更适合放项目简介、快速开始、常用链接。
Wiki更适合放详细说明。
比如一个后端项目,可以在Wiki里建这些页面:
本地开发环境生产环境部署接口鉴权说明数据库迁移说明常见报错处理
如果团队里经常有人问“这个项目怎么启动”“接口文档在哪”“部署命令是什么”,那就说明这些内容应该沉淀到Wiki里。
Release(版本发布)
Release是发布版本。
它不是简单地给源码打个包,而是用来记录某个版本发布了什么。
常见版本号大概是:
v1.0.0v1.1.0v1.2.0发布Release时,可以做这些事:
- 写更新日志
- 上传二进制文件
- 记录版本变更
- 标记这个版本对应的代码
比如一个v1.2.0版本可以这样写:
## v1.2.0
### 新增
- 添加考试成绩导出功能- 添加管理员操作日志
### 修复
- 修复登录失败时没有错误提示的问题- 修复部分页面刷新后状态丢失的问题
### 优化
- 优化首页加载速度这样以后回头看,就知道每个版本到底改了什么。
如果项目会提供可执行文件,比如桌面软件、命令行工具、服务端程序,也可以把编译好的文件上传到Release里。

Release适合回答这个问题:
这个版本发布了什么?用户应该下载哪个文件?出了问题应该回退到哪个版本?Watch(关注)、Star(收藏)、Fork(复制仓库)
如果你用过GitHub,这几个功能会很熟悉。Gitea里也有类似概念。
Star可以理解成收藏或点赞。
它一般表示:
我觉得这个项目有用,先收藏一下。Watch是关注更新。
如果你Watch了一个仓库,仓库有新Issue、Pull Request、Release等更新时,可能会收到通知。
Fork是复制仓库。
它会把别人的仓库复制一份到你的账号下面。你可以在自己的副本里修改代码,然后再向原仓库提交Pull Request。
简单区分:
Star:收藏项目Watch:关注更新Fork:复制一份仓库用于修改同一个团队内部开发,一般直接在原仓库开分支就行。
如果你没有原仓库的写权限,比如给开源项目贡献代码,通常就先Fork,再提交Pull Request。
一个完整例子
前面每个功能单独看可能有点散,下面用一个“在线考试系统”的例子串起来。
假设现在要做一个新功能:
添加考试成绩导出功能比较完整的协作流程可以是:
创建 Issue:添加考试成绩导出功能↓添加 Label:feature、backend↓加入 Milestone:v1.2.0↓分配给开发者↓放入 Project 看板 TODO↓开发者开始处理,移动到 Doing↓创建 feature-export 分支↓提交代码↓创建 Pull Request↓关联 Issue:Closes #12↓Code Review↓合并 PR↓Issue 自动关闭↓Project 卡片移动到 Done↓发布 Release:v1.2.0这样一条线下来,每一步都有记录。
别人想知道这个功能为什么做,可以看Issue。
想知道谁负责,可以看Assignee。
想知道属于哪个版本,可以看Milestone。
想知道现在进度,可以看Project。
想知道代码怎么改的,可以看Pull Request。
想知道最终发到哪个版本,可以看Release。
这就是Gitea项目协作功能的意义。
建议的学习顺序
如果按这个系列来看,可以这样排:
1. Gitea与Git配置2. Git基础使用教程3. Git协作流程4. Git冲突处理5. Gitea项目协作功能介绍6. Gitea组织与权限管理7. Gitea Actions使用8. Gitea部署记录前几篇解决的是“会不会用Git提交代码”。
从这篇开始,就进入“会不会管理项目协作”。
一个人写代码时,可能Issue、Milestone、Project这些东西都显得可有可无。但只要项目里有多人协作、有版本计划、有任务分配,这些功能就会变得很有用。
总结
Gitea不只是一个放代码的地方。
如果只用它来clone、push、创建Pull Request,那其实只用到了一部分能力。
更完整的项目协作应该是:
Issue 记录事情Label 分类任务Assignee 明确负责人Milestone 管理版本目标Project 跟踪任务进度Pull Request 合并代码Wiki 沉淀文档Release 发布版本先不用一上来把所有功能都用得很复杂。
小团队可以先从三个东西开始:
IssuePull RequestRelease等任务多了,再加Label、Milestone和Project。这样从“会写代码”慢慢过渡到“会管理项目”,协作会清楚很多。