Git学习笔记:Gitee API 从入门到实战,用 Go 打造你的代码托管自动化工作流

概述

Gitee API(v5)提供了完整的 RESTful 接口,让你可以通过 HTTP 请求完成几乎所有 Gitee 网页端能做的操作——从查询用户信息、管理仓库到推送文件内容。配合 Go 语言的 net/http 标准库,你可以快速搭建一套属于自己的代码托管自动化工具。

本文将覆盖 用户信息管理仓库生命周期操作仓库内容管理 三大核心模块,并分析 Gitee API 的局限性及替代方案。

官方文档: Gitee API v5 Swagger

前置准备:Token 认证

所有 API 请求都需要在 Header 中携带 Personal Access Token(Gitee 个人设置 → 私人令牌 生成):

req.Header.Set("Authorization", "Bearer "+token)

公共请求函数

每次请求都写一遍错误处理和 JSON 解析很繁琐,先封装一个通用函数,后续直接复用:

func giteeAPI(method, url string, body io.Reader) (interface{}, error) {
    req, _ := http.NewRequest(method, url, body)
    req.Header.Set("Authorization", "Bearer "+token)
    if body != nil {
        req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    }
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, fmt.Errorf("请求失败: %v", err)
    }
    defer resp.Body.Close()
    respBody, _ := io.ReadAll(resp.Body)
    var result interface{}
    json.Unmarshal(respBody, &result)
    return result, nil
}

1. 用户信息管理

1.1 查询当前用户信息

result, _ := giteeAPI("GET", "https://gitee.com/api/v5/user", nil)
pretty, _ := json.MarshalIndent(result, "", "  ")
fmt.Println(string(pretty))

参数: 无(使用 token 认证)

输出示例(返回值 - UserDetail):

{
  "id": 12345,                                                                  // 用户 ID
  "login": "cloud-drive-01",                                                    // 登录名
  "name": "cloud-drive-01",                                                     // 昵称
  "avatar_url": "https://gitee.com/assets/no_portrait.png",                     // 头像 URL
  "url": "https://gitee.com/api/v5/users/cloud-drive-01",                       // API 地址
  "html_url": "https://gitee.com/cloud-drive-01",                               // 个人主页
  "remark": "",                                                                  // 企业备注
  "followers_url": "https://gitee.com/api/v5/users/cloud-drive-01/followers",   // 关注者列表 API
  "following_url": "https://gitee.com/api/v5/users/cloud-drive-01/following",   // 正在关注列表 API
  "gists_url": "https://gitee.com/api/v5/users/cloud-drive-01/gists",           // 代码片段 API
  "starred_url": "https://gitee.com/api/v5/users/cloud-drive-01/starred",       // 收藏仓库 API
  "subscriptions_url": "https://gitee.com/api/v5/users/cloud-drive-01/subscriptions",  // 订阅 API
  "organizations_url": "https://gitee.com/api/v5/users/cloud-drive-01/orgs",    // 组织列表 API
  "repos_url": "https://gitee.com/api/v5/users/cloud-drive-01/repos",           // 仓库列表 API
  "events_url": "https://gitee.com/api/v5/users/cloud-drive-01/events",         // 动态 API
  "received_events_url": "https://gitee.com/api/v5/users/cloud-drive-01/received_events", // 收到的动态 API
  "type": "User",                                                               // 用户类型
  "member_role": "admin",                                                       // 成员角色
  "blog": "https://github.com/8002124177",                                      // 博客地址
  "weibo": "",                                                                  // 微博
  "bio": "我修改了我的个签",                                                       // 个人签名
  "public_repos": 5,                                                            // 公开仓库数
  "public_gists": 0,                                                            // 公开代码片段数
  "followers": 1,                                                               // 关注者数
  "following": 0,                                                               // 正在关注数
  "stared": 0,                                                                  // 收藏数
  "watched": 1,                                                                 // 关注数
  "created_at": "2024-01-01T00:00:00+08:00",                                   // 创建时间
  "updated_at": "2024-06-15T12:00:00+08:00",                                   // 更新时间
  "email": "user@example.com",                                                  // 邮箱
  "bot_info": null                                                              // 机器人信息
}

1.2 修改用户信息

body := "name=cloud-drive-01&bio=这是我修改的个人签名"
result, _ := giteeAPI("PATCH", "https://gitee.com/api/v5/user", strings.NewReader(body))
pretty, _ := json.MarshalIndent(result, "", "  ")
fmt.Println(string(pretty))

参数(formData 格式,全部可选):

参数 类型 说明
name string 昵称
blog string 个人网站
weibo string 微博
bio string 个人签名

输出示例: 同 1.1 返回结果,但少了 emailbot_info 两个字段。

1.3 查询用户所有仓库

result, _ := giteeAPI("GET",
    "https://gitee.com/api/v5/user/repos?visibility=private&per_page=5&page=1", nil)
pretty, _ := json.MarshalIndent(result, "", "  ")
fmt.Println(string(pretty))

参数(query 参数,全部可选):

参数 类型 说明
visibility string 筛选: private / public / all(默认 all)
affiliation string 筛选: owner / collaborator / organization_member / admin
type string 筛选: all / owner / personal / member / public / private(与 visibility/affiliation 冲突会返回 422)
sort string 排序: created / updated / pushed / full_name(默认 full_name)
direction string 升序 asc / 降序 desc
q string 搜索关键字
page int 页码(默认 1)
per_page int 每页条数(默认 20,最大 100)

输出示例: 返回 Project[] 数组,每个元素结构见 2.2 的输出示例。

扩展:更多用户相关 API

方法 路径 说明
GET /v5/user/followers 列出关注者
GET /v5/user/following 列出正在关注的用户
PUT /v5/user/following/{username} 关注一个用户
DELETE /v5/user/following/{username} 取消关注
GET /v5/user/keys 列出 SSH 公钥
POST /v5/user/keys 添加 SSH 公钥
GET /v5/user/orgs 列出所属组织
GET /v5/user/emails 查看邮箱信息

2. 仓库信息管理

2.1 创建仓库

data := "name=gitee-api-test-repo" +
    "&description=由 Gitee API 创建的测试仓库" +
    "&private=true&auto_init=true&gitignore_template=Go" +
    "&has_issues=true&has_wiki=true"

result, _ := giteeAPI("POST", "https://gitee.com/api/v5/user/repos", strings.NewReader(data))
pretty, _ := json.MarshalIndent(result, "", "  ")
fmt.Println(string(pretty))

参数(formData 格式):

参数 类型 必填 说明
name string 仓库名称
description string 仓库描述
private bool 是否私有
has_issues bool 是否开启 Issue(默认 true)
has_wiki bool 是否开启 Wiki(默认 true)
auto_init bool 是否初始化 README(默认 false)
gitignore_template string Git Ignore 模板(如 Go、Python)
license_template string License 模板(如 MIT、Apache-2.0)
homepage string 主页地址
path string 仓库路径(默认取 name)
namespace string 命名空间路径,不传则创建到个人
public int 0=私有,1=外部开源,2=内部开源
can_comment bool 是否允许评论(默认 true)
outsourced bool 是否外包仓库(默认 false)
members string 成员列表(逗号分隔)

常见错误:

{"error": {"base": ["已存在同地址仓库(忽略大小写)"]}}

输出示例: 返回字段同查询仓库详情(2.2),成功状态码为 201 Created

2.2 查询仓库详情

result, _ := giteeAPI("GET",
    "https://gitee.com/api/v5/repos/cloud-drive-01/gitee-api-test-repo", nil)
pretty, _ := json.MarshalIndent(result, "", "  ")
fmt.Println(string(pretty))

参数(path 参数):

参数 类型 必填 说明
owner string 仓库所属空间(个人/企业/组织路径)
repo string 仓库路径

输出示例(返回值 - Project):

{
  "id": 12345678,                                                              // 仓库 ID
  "full_name": "cloud-drive-01/gitee-api-test-repo",                          // 完整仓库名
  "human_name": "gitee-api-test-repo",                                        // 人类可读名称
  "url": "https://gitee.com/api/v5/repos/cloud-drive-01/gitee-api-test-repo", // API 地址
  "html_url": "https://gitee.com/cloud-drive-01/gitee-api-test-repo",         // 网页地址
  "description": "由 Gitee API 创建的测试仓库",                                   // 仓库描述
  "private": true,                                                            // 是否私有
  "owner": {                                                                  // 仓库所有者
    "id": 12345, "login": "cloud-drive-01", "name": "cloud-drive-01",
    "avatar_url": "https://gitee.com/assets/no_portrait.png"
  },
  "default_branch": "master",                                                 // 默认分支
  "language": "Go",                                                           // 主要语言
  "has_issues": true,                                                         // 是否开启 Issue
  "has_wiki": true,                                                           // 是否开启 Wiki
  "fork": false,                                                              // 是否为 Fork
  "open_issues_count": 0,                                                     // 开启的 Issue 数
  "created_at": "2024-06-01T10:00:00+08:00",                                  // 创建时间
  "updated_at": "2024-06-15T12:00:00+08:00"                                   // 更新时间
}

2.3 修改仓库信息

data := "name=gitee-api-tes-repo&description=修改了描述信息&has_issues=false"
result, _ := giteeAPI("PATCH",
    "https://gitee.com/api/v5/repos/cloud-drive-01/gitee-api-tes-repo",
    strings.NewReader(data))
pretty, _ := json.MarshalIndent(result, "", "  ")
fmt.Println(string(pretty))

参数: 除 2.2 的 ownerrepo 外,额外支持:

参数 类型 必填 说明
name string 仓库名称
description string 仓库描述
homepage string 主页地址
private bool 是否私有
path string 修改仓库路径
default_branch string 设置默认分支
has_issues bool 是否开启 Issue
has_wiki bool 是否开启 Wiki

输出示例: 同 2.2 的 Project 结构,字段值反映修改后的内容。

2.4 删除仓库

url := "https://gitee.com/api/v5/repos/cloud-drive-01/gitee-api-tes-repo"
req, _ := http.NewRequest("DELETE", url, nil)
req.Header.Set("Authorization", "Bearer "+token)

resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
fmt.Printf("状态码: %d\n", resp.StatusCode)
body, _ := io.ReadAll(resp.Body)
fmt.Printf("返回体: %s\n", string(body))

参数: ownerrepo(同 2.2)

输出示例:

状态码: 204   // 删除成功,不返回内容
状态码: 404   // 仓库不存在,返回: {"message":"Not Found Project"}

2.5 清空仓库

清空仓库中的所有文件内容,但保留仓库本身。

url := "https://gitee.com/api/v5/repos/cloud-drive-01/upload-test/clear"
req, _ := http.NewRequest("PUT", url, nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
fmt.Printf("状态码: %d\n", resp.StatusCode)  // 204 表示成功

参数: ownerrepo(同 2.2)

输出示例: 状态码: 204(仓库已清空,本身还在)

扩展:更多仓库管理 API

方法 路径 说明
GET /v5/repos/{owner}/{repo}/branches 列出仓库分支
POST /v5/repos/{owner}/{repo}/branches 创建分支
GET /v5/repos/{owner}/{repo}/tags 列出标签
POST /v5/repos/{owner}/{repo}/tags 创建标签
GET /v5/repos/{owner}/{repo}/contributors 获取贡献者
GET /v5/repos/{owner}/{repo}/forks 查看 Forks
POST /v5/repos/{owner}/{repo}/forks Fork 仓库
GET /v5/repos/{owner}/{repo}/hooks 管理 Webhooks
GET /v5/repos/{owner}/{repo}/releases 管理 Releases

3. 仓库内容管理

3.1 提交推送记录(Commits API)

一次提交可以同时执行多个操作:创建、更新、重命名、移动、删除文件。这是 Gitee API 最强大的功能之一。

批量上传:遍历本地目录构建操作列表

actions := []map[string]string{}
filepath.Walk("upload", func(path string, info os.FileInfo, err error) error {
    if info.IsDir() {
        return nil
    }
    relPath := filepath.ToSlash(path)
    data, _ := os.ReadFile(path)
    ext := strings.ToLower(filepath.Ext(path))
    encoding := "text"
    content := string(data)
    if ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif" || ext == ".ico" {
        encoding = "base64"
        content = base64.StdEncoding.EncodeToString(data)
    }
    actions = append(actions, map[string]string{
        "action": "create", "path": relPath, "content": content, "encoding": encoding,
    })
    return nil
})
body := map[string]interface{}{
    "branch": "master", "message": "上传本地文件", "actions": actions,
}
jsonData, _ := json.Marshal(body)
req, _ := http.NewRequest("POST",
    "https://gitee.com/api/v5/repos/cloud-drive-01/upload-test/commits",
    bytes.NewReader(jsonData))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
var v interface{}
json.Unmarshal(respBody, &v)
pretty, _ := json.MarshalIndent(v, "", "  ")
fmt.Printf("状态码: %d\n%s\n", resp.StatusCode, string(pretty))

多类型操作:一次提交完成创建/更新/重命名/移动/删除

commit := map[string]interface{}{
    "branch": "master", "message": "对已有文件进行操作:更新/重命名/移动/删除",
    "actions": []map[string]string{
        // 更新内容
        {"action": "update", "path": "src/main.go",
            "content": "package main\nimport \"fmt\"\nfunc main() {\n\tfmt.Println(\"v2\")\n}",
            "encoding": "text"},
        // 重命名 docs/readme.txt → docs/intro.txt
        {"action": "move", "path": "docs/intro.txt",
            "previous_path": "docs/readme.txt", "content": "这是改名后的文件", "encoding": "text"},
        // 移动 scripts/build.sh → tools/build.sh
        {"action": "move", "path": "tools/build.sh",
            "previous_path": "scripts/build.sh", "content": "echo build v2", "encoding": "text"},
        // 删除
        {"action": "delete", "path": "config/app.yaml"},
        // 新增
        {"action": "create", "path": "CHANGELOG.md",
            "content": "# Changelog\n\n## v1.0\n- 初始版本", "encoding": "text"},
    },
}
// 请求方式同上

Action 参数一览:

action 说明 必填参数
create 创建新文件 pathcontentencoding
update 更新已有文件 pathcontentencoding
move 重命名/移动文件 pathcontentencodingprevious_path
delete 删除文件 path

输出示例(返回值 - Commit):

{
  "sha": "a1b2c3d4e5f6...",                      // 提交 SHA
  "commit": {                                      // 提交详情
    "message": "上传本地文件",                       // 提交信息
    "author": { "name": "pc2005", "date": "..." }, // 作者
    "committer": { "name": "pc2005", "date": "..." } // 提交者
  },
  "html_url": "https://gitee.com/cloud-drive-01/upload-test/commit/a1b2c3d..." // 网页链接
}

3.2 获取文件列表

url := fmt.Sprintf("https://gitee.com/api/v5/repos/%s/%s/contents", owner, repo)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var v interface{}
json.Unmarshal(body, &v)
pretty, _ := json.MarshalIndent(v, "", "  ")
fmt.Printf("=== 根目录 ===\n%s\n", string(pretty))

参数(path + query):

参数 类型 必填 说明
ownerrepo string 仓库所属空间和仓库名(同 2.2)
path string 目录路径(空字符串 = 根目录)
ref string 分支/tag/commit(默认 master)

输出示例(返回值 - FileContent[]):

[
  {
    "_links": {                                                                 // 链接集合
      "html": "https://gitee.com/cloud-drive-01/upload-test/blob/master/assets",  // 网页链接
      "self": "https://gitee.com/api/v5/repos/cloud-drive-01/upload-test/contents/assets" // API 链接
    },
    "download_url": "https://gitee.com/cloud-drive-01/upload-test/raw/master/assets",  // 下载链接
    "html_url": "https://gitee.com/cloud-drive-01/upload-test/blob/master/assets",      // 网页地址
    "name": "assets",                                                           // 文件名
    "path": "assets",                                                           // 路径
    "sha": "247dbf206f88150f34187a7f6e48b5fefb190fd5",                         // 文件 SHA
    "size": null,                                                               // 文件大小(目录为 null)
    "type": "dir",                                                              // 类型: "file" 或 "dir"
    "url": "https://gitee.com/api/v5/repos/cloud-drive-01/upload-test/contents/assets" // 资源 URL
  }
]

3.3 下载单个文件(Raw)

url := fmt.Sprintf("https://gitee.com/api/v5/repos/cloud-drive-01/%s/raw/hello.txt", repo)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
content, _ := io.ReadAll(resp.Body)
fmt.Printf("状态码: %d\n内容: %s\n", resp.StatusCode, string(content))

参数: ownerrepopath(文件路径),同 2.2 的 path 参数格式。

输出示例: 文件原始内容,支持最大 100MB

3.4 单个文件 CRUD(Contents API)

适合操作单个文件,批量操作推荐使用 3.1 的 Commits API。

方法 路径 说明
POST /v5/repos/{owner}/{repo}/contents/{path} 新建文件
PUT /v5/repos/{owner}/{repo}/contents/{path} 更新文件
DELETE /v5/repos/{owner}/{repo}/contents/{path} 删除文件

输出示例: 成功返回 Commit 对象(同 3.1 的返回结构)。

4. Git Data API(只读)

Gitee 只提供了两个 Git Data 读取接口,没有写入接口,这是与 GitHub API 的一个显著差异。

方法 路径 说明
GET /v5/repos/{owner}/{repo}/git/blobs/{sha} 通过 Blob SHA 获取文件原始内容
GET /v5/repos/{owner}/{repo}/git/trees/{sha} 获取目录树结构(支持 ?recursive=1 递归)

输出示例(Blob):

{
  "sha": "247dbf206f88150f34187a7f6e48b5fefb190fd5",  // Blob SHA
  "size": 1024,                                        // 文件大小(字节)
  "encoding": "base64",                                // 编码方式
  "content": "cGFja2FnZSBtYWlu...\n"                   // 文件内容(Base64 编码)
}

输出示例(Tree):

{
  "sha": "3b88c5b8a7e9d1f2...",                       // Tree SHA
  "tree": [                                             // 文件树条目
    {
      "path": "src",                                   // 路径
      "mode": "040000",                                // 文件模式
      "type": "tree",                                  // 类型: blob / tree / commit
      "sha": "a1b2c3d4e5f6...",                       // 条目 SHA
      "size": null                                     // 文件大小(目录为 null)
    },
    {
      "path": "README.md",
      "mode": "100644",
      "type": "blob",
      "sha": "d4e5f6a7b8c9...",
      "size": 512                                      // 文件大小(字节)
    }
  ]
}

总览:API 端点速查表

用户管理

方法 路径 功能
GET /v5/user 获取当前用户信息
PATCH /v5/user 修改用户信息
GET /v5/user/repos 列出用户仓库
POST /v5/user/repos 创建仓库

仓库管理

方法 路径 功能
GET /v5/repos/{owner}/{repo} 查询仓库信息
PATCH /v5/repos/{owner}/{repo} 修改仓库信息
DELETE /v5/repos/{owner}/{repo} 删除仓库
PUT /v5/repos/{owner}/{repo}/clear 清空仓库

内容管理

方法 路径 功能
GET /v5/repos/{owner}/{repo}/contents(/{path}) 获取目录内容/文件列表
POST /v5/repos/{owner}/{repo}/contents/{path} 新建文件
PUT /v5/repos/{owner}/{repo}/contents/{path} 更新文件
DELETE /v5/repos/{owner}/{repo}/contents/{path} 删除文件
POST /v5/repos/{owner}/{repo}/commits 提交文件变更(批量)
GET /v5/repos/{owner}/{repo}/raw/{path} 下载 raw 文件(≤100MB)

Git Data(只读)

方法 路径 功能
GET /v5/repos/{owner}/{repo}/git/blobs/{sha} 获取文件 Blob
GET /v5/repos/{owner}/{repo}/git/trees/{sha} 获取目录 Tree

局限性与替代方案

已知问题:

  1. Git Data API 只有读操作:仅有 GET blobGET tree,没有 create blobcreate treecreate commitupdate ref 等写入接口。
  2. 场景受限:例如「清空历史提交保留最新一个」这种需求,标准的 Git Data API(GitHub)可以通过 创建新 blob → 新 tree → 新 commit → 更新 ref 实现,但 Gitee 无法做到。

替代方案:

  • 缺失的 Git Data 写入能力,可用本地 git 命令 + 3.1 的 Commits API 组合替代。
  • 需要完整的 Git Data 写入(git/refsgit/commitsgit/treesgit/blobs),建议考虑 GitHub API。

结语

Gitee API v5 覆盖了日常代码托管的大部分场景:用户管理、仓库生命周期、文件内容管理等,足以支撑自动化工作流和个人效率工具的构建。Go 语言的 net/http 标准库加上 encoding/json,就可以完成全部调用,无需额外依赖。

posted @ 2026-08-10 23:39  PC2005-cloud  阅读(36)  评论(0)    收藏  举报